AutoEmail - 写了个监听文件修改,自动发送修改文件提示邮件的程序
AutoEmail - 写了个监听文件修改,自动发送修改文件提示邮件的程序
由于时间比较赶,现学一下午写的,很多细节没有考虑清楚,总体来说程序的鲁棒性并不算强。
链接:https://pan.baidu.com/s/1raxz-jlTmWib0gHi6YSSGw
提取码:zsrj
内含Java环境,没装Java环境需要先装好。(实在没弄明白Exe4j和inno怎么用,做出来的setup还是不能在无jre机器上跑)
1 配置发件人邮箱
发送邮件首先需要有一个邮箱账号和密码,本文以QQ邮箱为例,邮箱账号必须要开启SMTP 服务,操作步骤如下:
-
首先登录网页版QQ邮箱(https://mail.qq.com)
-
点击“设置”
-
点击“账户”
-
向下滑动,找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务”
开启
POP3/SMTP
服务(示例图中已经开启) -
点击“生成授权码”,按照提示完成操作
请记录这一步的授权码,方便后面使用。
2 监听文件
在进行这一步操作前,请确保你已经按照要求完成了步骤1。
-
填写发件人
发件人即你用来发送邮件的邮箱地址,本程序仅支持QQ/163/126邮箱。
-
填写密码
这个密码并非qq邮箱的登录密码,而是第一步中的授权码。
-
填写收件人
收件人即用来接收邮件的邮箱地址,这个地址可以是任何邮箱。
-
填写监听文件路径
为了防止用户手动输入错误,此路径不能通过直接编辑更改。请点击“选择文件”按钮来选择你想要监听的文件。
-
设置监听间隔(秒)
监听间隔表示程序每隔多少秒监测一次目标文件是否被修改。在程序启动时,这个监听间隔被默认设置为60秒,你也可以手动输入一个\(\geqslant 1\)的整数来改变它。
最后,点击“开始/结束监测”,即可开始监听(再次按下本按钮可以停止监测)。
3 【推荐】导入已有的配置
为了避免每次运行本程序时,都需要重复填写一边收件人等基本信息,你可以将这些信息预先写入一个.txt
文本文件中。
这个.txt
文本文件记录着发件人、密码、收件人、监听文件、监听间隔。你应该仿照图例来编写此文件。
然后将该文件存储到一个位置(本例中,我们将其命名为'conf.txt',你也可以更改为其他的名称)。然后,我们只需要点击导入已有配置
按钮,选择刚刚存储的这个conf.txt
,配置的信息就会被自动填充到程序中,最后点击开始/结束监测
按钮即可。
4 组织结构及源码
GUI.java
package frame;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Label;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import utils.MailUtils;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.regex.Pattern;
import java.awt.event.ActionEvent;
public class GUI extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private JTextField fromField;
private JTextField toField;
private JTextField attachField;
private JTextField passwordField;
private int version = 0;
private File checkFile;
private Long lastModified;
private int checkFreq;
private boolean status;
private Thread checkThread;
private JTextField freqField;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI frame = new GUI();
frame.setVisible(true);
} catch (Exception e) {
JOptionPane.showConfirmDialog(null,"图形用户界面创建失败","系统消息",JOptionPane.CLOSED_OPTION);
e.printStackTrace();
}
}
});
}
public GUI() {
status = false;
checkFreq = 60;
/* 设定主窗口的基本参数 */
setSize(600,400);
setLocationRelativeTo(null);
setVisible(true);
setTitle("AutoEmail");
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
contentPane = new JPanel();
contentPane.setForeground(new Color(153, 204, 255));
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
int choice = JOptionPane.showConfirmDialog(null,"您确定要退出吗?","系统消息",JOptionPane.YES_NO_OPTION);
if(choice == JOptionPane.YES_OPTION) {
System.exit(0);
}
}
});
freqField = new JTextField();
freqField.setText("60");
freqField.setBounds(172, 263, 84, 21);
contentPane.add(freqField);
freqField.setColumns(10);
JLabel freqLabel = new JLabel("\u76D1\u542C\u95F4\u9694\uFF08\u79D2\uFF09");
freqLabel.setBounds(29, 266, 93, 15);
contentPane.add(freqLabel);
JLabel fromLabel = new JLabel("\u53D1\u4EF6\u4EBA");
fromLabel.setBounds(29, 34, 54, 15);
contentPane.add(fromLabel);
JLabel passwordLabel = new JLabel("\u5BC6\u7801");
passwordLabel.setBounds(29, 89, 54, 15);
contentPane.add(passwordLabel);
JLabel toLabel = new JLabel("\u6536\u4EF6\u4EBA");
toLabel.setBounds(29, 154, 54, 15);
contentPane.add(toLabel);
JLabel attachPathLabel = new JLabel("\u76D1\u6D4B\u6587\u4EF6\u8DEF\u5F84");
attachPathLabel.setBounds(29, 211, 93, 15);
contentPane.add(attachPathLabel);
fromField = new JTextField();
fromField.setBounds(167, 31, 386, 21);
contentPane.add(fromField);
fromField.setColumns(10);
passwordField = new JTextField();
passwordField.setBounds(167, 86, 386, 21);
contentPane.add(passwordField);
passwordField.setColumns(10);
toField = new JTextField();
toField.setColumns(10);
toField.setBounds(167, 151, 386, 21);
contentPane.add(toField);
attachField = new JTextField();
attachField.setBackground(Color.YELLOW);
attachField.setEditable(false);
attachField.setColumns(10);
attachField.setBounds(169, 208, 246, 21);
contentPane.add(attachField);
JButton attachChooseButton = new JButton("\u9009\u62E9\u6587\u4EF6");
attachChooseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.showDialog(new Label(), "选择监听文件");
File file = chooser.getSelectedFile();
if(file != null) {
JOptionPane.showConfirmDialog(null, "选择文件成功", "系统消息", JOptionPane.CLOSED_OPTION);
attachField.setText(file.getAbsolutePath().toString());
}
}
});
attachChooseButton.setBounds(458, 207, 93, 23);
contentPane.add(attachChooseButton);
JButton startButton = new JButton("\u5F00\u59CB/\u7ED3\u675F\u76D1\u6D4B");
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!Pattern.compile("^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$").matcher(
fromField.getText()).matches()) {
JOptionPane.showConfirmDialog(null, "请检查邮箱格式", "邮箱格式错误", JOptionPane.CLOSED_OPTION);
}else if(!Pattern.compile("^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$").matcher(
toField.getText()).matches()) {
JOptionPane.showConfirmDialog(null, "请检查邮箱格式", "邮箱格式错误", JOptionPane.CLOSED_OPTION);
}else if(passwordField.getText().isEmpty()) {
JOptionPane.showConfirmDialog(null, "请输入stmp授权码(请参考用户手册)", "授权码为空", JOptionPane.CLOSED_OPTION);
}else if(attachField.getText().isEmpty()) {
JOptionPane.showConfirmDialog(null, "请选择待监听的文件", "未选择文件", JOptionPane.CLOSED_OPTION);
}else if(freqField.getText().isEmpty()){
JOptionPane.showConfirmDialog(null, "请选择监听间隔时间", "间隔时间不合法", JOptionPane.CLOSED_OPTION);
}else if(status == false){
checkFreq = Integer.valueOf(freqField.getText());
status = true;
MailUtils utils = new MailUtils();
utils.init(fromField.getText(), passwordField.getText(), toField.getText());
checkFile = new File(attachField.getText());
lastModified = checkFile.lastModified();
checkThread = new Thread() {
public void run() {
while(status) {
Long currModified = checkFile.lastModified();
try {
if(currModified.longValue() != lastModified.longValue()) {
utils.sendMessage("检测到文件更新[" + version + "]",
"更新时间: " + (new Date(currModified)).toString(), attachField.getText());
lastModified = currModified;
version += 1;
}
Thread.sleep(1000 * checkFreq);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
checkThread.start();
JOptionPane.showConfirmDialog(null, "已开始监听", "系统消息", JOptionPane.CLOSED_OPTION);
}else {
JOptionPane.showConfirmDialog(null, "已停止监听", "系统消息", JOptionPane.CLOSED_OPTION);
status = false;
}
}
});
startButton.setBounds(368, 312, 122, 31);
contentPane.add(startButton);
JButton confButton = new JButton("\u5BFC\u5165\u5DF2\u6709\u914D\u7F6E");
confButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.showDialog(new Label(), "选择配置文件");
File file = chooser.getSelectedFile();
String[] conf = new String[10];
int ptr = 0;
if(file != null) {
try {
InputStreamReader reader = new InputStreamReader(
new FileInputStream(file));
BufferedReader br = new BufferedReader(reader);
String line = "";
line = br.readLine();
while(line != null) {
conf[ptr++] = line;
line = br.readLine();
}
br.close();
fromField.setText(conf[0]);
passwordField.setText(conf[1]);
toField.setText(conf[2]);
attachField.setText(conf[3]);
freqField.setText(conf[4]);
checkFreq = Integer.valueOf(conf[4]);
} catch (IOException e) {
JOptionPane.showConfirmDialog(null,"文件读入错误", "系统错误",JOptionPane.CLOSED_OPTION);
}
}
}
});
confButton.setBounds(116, 312, 122, 31);
contentPane.add(confButton);
}
}
MailUtils.java
package utils;
import java.util.*;
import java.util.regex.Pattern;
import javax.mail.*;
import javax.mail.internet.*;
import javax.swing.JOptionPane;
import javax.activation.*;
public class MailUtils{
private String from;
private String host;
private String password;
private String to;
private Session session;
public void init(String _from, String _password, String _to) {
from = _from;
password = _password;
to = _to;
if(Pattern.compile("^.*@qq.com$").matcher(from).matches()) {
host = "smtp.qq.com";
}else if(Pattern.compile("^.*@163.com$").matcher(from).matches()) {
host = "smtp.163.com";
}else if(Pattern.compile("^.*@126.com$").matcher(from).matches()) {
host = "smtp.126.com";
}else {
JOptionPane.showConfirmDialog(null, "仅支持QQ/163/126邮箱作为发件人", "发件人错误", JOptionPane.CLOSED_OPTION);
}
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true");
session = Session.getDefaultInstance(properties, new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from, password);
}
});
}
public void sendMessage(String subject, String text, String attachment) {
try {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
Multipart multipart = new MimeMultipart();
BodyPart textPart = new MimeBodyPart();
textPart.setText(text);
BodyPart attachPart = new MimeBodyPart();
DataSource source = new FileDataSource(attachment);
attachPart.setDataHandler(new DataHandler(source));
attachPart.setFileName(attachment);
multipart.addBodyPart(textPart);
multipart.addBodyPart(attachPart);
message.setContent(multipart);
Transport.send(message);
System.out.println("发送成功!");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}