Quartz Timed Mail Sends Multiple Backup Files - Black Shell

Posted by medaswho on Sun, 09 Jun 2019 22:53:42 +0200

This article is based on Black Shell Mesh Release

Source of this article Quartz Timed Mail to Send Backup Files - Black Shell Network http://www.bhusk.com/articles/2017/07/27/1501146724360.html

Uncle Shell had a funny moment

text

Previously, due to the black shell blog database, has not done regular backup processing, although not necessarily a problem now, but at least the awareness of data backup still needs to be.

We have considered using third-party services such as Qiniuyun before, but in the end, for various reasons, we do not consider using third-party services for the time being.
So I wrote a timed backup program by myself. Simple idea_

Upon reaching the designated time, the database backup files are sent to the designated mailbox to achieve the purpose of regular backup.

Special note: If the file requires high security, it is not recommended.

The program uses Java language and maven's powerful dependency system + popular spring, why use Java, just write fun not too true.

Project code

pom.xml file
Quartz's package is indispensable to the whole project

 <properties>
        <!-- Spring Version of _____________ -->
        <springframework.version>4.0.6.RELEASE</springframework.version>
        <!-- Quartz Version of _____________ -->
        <quartz.version>2.2.1</quartz.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/javax.mail/mail -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>${quartz.version}</version>
        </dependency>

        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springframework.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
    </dependencies>

MyJob.java inherits QuartzJobBean and then Override
You can look at Quartz JobBean bit by bit with a bit of research spirit.

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.util.Date;

/**
 * kzyuan Job Reference resources
 * @description black husk
 * @description http://www.bhusk.com
 */
public class MyJob extends QuartzJobBean {

    private static Logger logger = LoggerFactory.getLogger(DatabaseBackupJob.class);

    @Override
    protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {

        System.out.println("execution time:"+new Date());
    }
}

application.xml can be understood as a quartz configuration file with complete annotations

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

    <!-- Defining tasks bean -->
    <bean name="myJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <!-- Specify specific job class -->
        <property name="jobClass" value="com.bhusk.quartz.Job.MyJob"/>
        <!-- Appoint job Name of -->
        <property name="name" value="myJob"/>
        <!-- Appoint job Grouping -->
        <property name="group" value="jobs"/>
        <!-- Must be set to true,If false,Delete the task in the scheduler when an inactive trigger is associated with it  -->
        <property name="durability" value="true"/>
        <!-- Appoint spring Container key,If not set at job Medium jobmap It's not available. spring Container -->
        <property name="applicationContextJobDataKey" value="applicationContext"/>
    </bean>

    <!-- Define triggers -->
    <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="myJobDetail"/>
        <!--execution time -->
        <property name="cronExpression" value="0 0 3 * * ?"/>
    </bean>

    <!-- Define triggers -->
     <!--Demo: One job There can be multiple trigger; -->
    <!--<bean id="cronTrigger2" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">-->
    <!--<property name="jobDetail" ref="myJobDetail2" />-->
    <!--Execute once a minute-->
    <!--    <property name="cronExpression" value="0 0 3 * * ?"/> -->
     <!--</bean>-->

    <!-- Define scheduler -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger"/>
     <!--         <ref bean="cronTrigger2"/> -->
            </list>
        </property>
    </bean>

</beans>

JavaMail Send Mail Tool Class
java implements sending, copying and multiple attachments of mail
The exact location of the tool source network is not clear.

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import java.io.UnsupportedEncodingException;
import java.util.Properties;

/**
 * Mail Manager
 * java Sending, Copying and Multiple Attachments of Mail
 */
public class EmailManager {

    public static String username = "keshu@bhusk.com"; // Service mailbox (from mailbox)
    public static String password = ""; // Password
    public static String senderNick = "Shell uncle of black shell reticulation";   // Sender's nickname

    private Properties props; // System attributes
    private Session session; // Mail session object
    private MimeMessage mimeMsg; // MIME mail object
    private Multipart mp;   // Multipart objects, mail content, headings, attachments, etc. are added to them and then regenerated into MimeMessage objects.

    private static EmailManager instance = null;

    public EmailManager() {
        props = System.getProperties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.host", "smtp.163.com");
        props.put("mail.smtp.port", "25");
        props.put("username", username);
        props.put("password", password);
        // Setting up a conversation
        session = Session.getDefaultInstance(props);
        session.setDebug(false);
    }

    public static EmailManager getInstance() {
        if (instance == null) {
            instance = new EmailManager();
        }
        return instance;
    }

    /**
     * Send mail
     *
     * @param from     Sender
     * @param to       Addressee
     * @param copyto   CC
     * @param subject  theme
     * @param content  content
     * @param fileList Annex List
     * @return
     */
    public boolean sendMail(String from, String[] to, String[] copyto, String subject, String content, String[] fileList) {
        boolean success = true;
        try {
            mimeMsg = new MimeMessage(session);
            mp = new MimeMultipart();

            // Custom sender nickname
            String nick = "";
            try {
                nick = javax.mail.internet.MimeUtility.encodeText(senderNick);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // Setting up sender
//          mimeMsg.setFrom(new InternetAddress(from));
            mimeMsg.setFrom(new InternetAddress(from, nick));
            // Setting up recipients
            if (to != null && to.length > 0) {
                String toListStr = getMailList(to);
                mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toListStr));
            }
            // Setting up a Copier
            if (copyto != null && copyto.length > 0) {
                String ccListStr = getMailList(copyto);
                mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccListStr));
            }
            // set up themes
            mimeMsg.setSubject(subject);
            // Setting text
            BodyPart bp = new MimeBodyPart();
            bp.setContent(content, "text/html;charset=utf-8");
            mp.addBodyPart(bp);
            // Setting Accessories
            if (fileList != null && fileList.length > 0) {
                for (int i = 0; i < fileList.length; i++) {
                    bp = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(fileList[i]);
                    bp.setDataHandler(new DataHandler(fds));
                    bp.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B"));
                    mp.addBodyPart(bp);
                }
            }
            mimeMsg.setContent(mp);
            mimeMsg.saveChanges();
            // Send mail
            if (props.get("mail.smtp.auth").equals("true")) {
                Transport transport = session.getTransport("smtp");
                transport.connect((String) props.get("mail.smtp.host"), (String) props.get("username"), (String) props.get("password"));
//              transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO));
//              transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.CC));
                transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
                transport.close();
            } else {
                Transport.send(mimeMsg);
            }
            System.out.println("Successful mail delivery");
        } catch (MessagingException e) {
            e.printStackTrace();
            success = false;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            success = false;
        }
        return success;
    }

    /**
     * Send mail
     *
     * @param from     Sender
     * @param to       Recipient, multiple emails separated by English commas
     * @param cc       Copy, multiple emails separated by English commas
     * @param subject  theme
     * @param content  content
     * @param fileList Annex List
     * @return
     */
    public boolean sendMail(String from, String to, String cc, String subject, String content, String[] fileList) {
        boolean success = true;
        try {
            mimeMsg = new MimeMessage(session);
            mp = new MimeMultipart();

            // Custom sender nickname
            String nick = "";
            try {
                nick = javax.mail.internet.MimeUtility.encodeText(senderNick);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            // Setting up sender
//          mimeMsg.setFrom(new InternetAddress(from));
            mimeMsg.setFrom(new InternetAddress(from, nick));
            // Setting up recipients
            if (to != null && to.length() > 0) {
                mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            }
            // Setting up a Copier
            if (cc != null && cc.length() > 0) {
                mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
            }
            // set up themes
            mimeMsg.setSubject(subject);
            // Setting text
            BodyPart bp = new MimeBodyPart();
            bp.setContent(content, "text/html;charset=utf-8");
            mp.addBodyPart(bp);
            // Setting Accessories
            if (fileList != null && fileList.length > 0) {
                for (int i = 0; i < fileList.length; i++) {
                    bp = new MimeBodyPart();
                    FileDataSource fds = new FileDataSource(fileList[i]);
                    bp.setDataHandler(new DataHandler(fds));
                    bp.setFileName(MimeUtility.encodeText(fds.getName(), "UTF-8", "B"));
                    mp.addBodyPart(bp);
                }
            }
            mimeMsg.setContent(mp);
            mimeMsg.saveChanges();
            // Send mail
            if (props.get("mail.smtp.auth").equals("true")) {
                Transport transport = session.getTransport("smtp");
                transport.connect((String) props.get("mail.smtp.host"), (String) props.get("username"), (String) props.get("password"));
                transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
                transport.close();
            } else {
                Transport.send(mimeMsg);
            }
            System.out.println("Successful mail delivery");
        } catch (MessagingException e) {
            e.printStackTrace();
            success = false;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            success = false;
        }
        return success;
    }

    public String getMailList(String[] mailArray) {
        StringBuffer toList = new StringBuffer();
        int length = mailArray.length;
        if (mailArray != null && length < 2) {
            toList.append(mailArray[0]);
        } else {
            for (int i = 0; i < length; i++) {
                toList.append(mailArray[i]);
                if (i != (length - 1)) {
                    toList.append(",");
                }

            }
        }
        return toList.toString();
    }

    public static void main(String[] args) {
        String from = username;
        String[] to = {"keshu@bhusk.com", "1520812121@qq.com"};
        String[] copyto = {"lu12121@qq.com"};
        String subject = "Black Shell Database Backup";
        String content = "Without data, there will be nothing. Database backup is a powerful means to prevent disaster. Without data, application is also fancy in the mirror.";
        String[] fileList = new String[2];
        fileList[0] = "~/solo_h2/db.mv.db";
        fileList[1] = "~/solo_h2/db.trace.db";

        EmailManager.getInstance().sendMail(from, to, copyto, subject, content, fileList);
    }
}

Reference project GitHub

Reference project GitHub: https://github.com/ykz200/Quartz_DatabaseBackup

Topics: Spring Session Java shell