Java Swing application for sending e-mail (with attachments)
- Details
- Written by Nam Ha Minh
- Last Updated on 04 May 2023   |   Print Email
This tutorial will teach you how to develop a Java Swing application that sends e-mail messages (with an optional attachment) from a SMTP account. The application would look like this:
The SMTP settings can be configured in a dialog which is accessible from menu File > Settings… as follows:
Work flow of the application is explained in the following diagram:
As we can see, the Swing application acts as an e-mail client that connects to a remote SMTP server for sending e-mail. Setting for the SMTP server is stored in smtp.propertiesfile with the following content:
mail.smtp.host=smtp.gmail.com mail.smtp.port=587 mail.user=codejava.net@gmail.com mail.password=secret mail.smtp.starttls.enable=true mail.smtp.auth=true
This is a typical SMTP setting for a GMail account. You should change the mail.userand mail.password according to your account. The e-mail address here will be displayed as sender in the out-going e-mail message. Put this file under the application’s directory.
The application needs JavaMail API to work, so download latest version of JavaMail here. And put the javax.mail.jar file under your project’s classpath.
The following class diagram describes how the application would be designed:
The application consists of four main classes:
- EmailUtility.java: implements a function for sending an e-mail message including attachments. See the article Send e-mail with attachment in Java for more details.
- ConfigUtility.java: implements two functions for reading and writing SMTP settings from/to the smtp.properties file as described above. For details, read the tutorial Reading and writing configuration for Java application using Properties class.
- SettingsDialog.java: implements a user interface that allows the user to update SMTP settings.
- SwingEmailSender.java: is the main entry of the application, it builds the main user interface that displays e-mail sending form and connects all the above pieces together. To allow the user to add a file as attachment, this class uses the JFilePicker class which is introduced in this article: File picker component in Swing.
1. Coding the EmailUtility class
This class is very straightforward with only one static, generic function sendEmail() which will be used by the SwingEmailSender class. Here’s its code:
package net.codejava.swing.mail; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; /** * A utility class that sends an e-mail message with attachments. * @author www.codejava.net * */ public class EmailUtility { public static void sendEmail(Properties smtpProperties, String toAddress, String subject, String message, File[] attachFiles) throws AddressException, MessagingException, IOException { final String userName = smtpProperties.getProperty("mail.user"); final String password = smtpProperties.getProperty("mail.password"); // creates a new session with an authenticator Authenticator auth = new Authenticator() { public PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(userName, password); } }; Session session = Session.getInstance(smtpProperties, auth); // creates a new e-mail message Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress(userName)); InternetAddress[] toAddresses = { new InternetAddress(toAddress) }; msg.setRecipients(Message.RecipientType.TO, toAddresses); msg.setSubject(subject); msg.setSentDate(new Date()); // creates message part MimeBodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setContent(message, "text/html"); // creates multi-part Multipart multipart = new MimeMultipart(); multipart.addBodyPart(messageBodyPart); // adds attachments if (attachFiles != null && attachFiles.length > 0) { for (File aFile : attachFiles) { MimeBodyPart attachPart = new MimeBodyPart(); try { attachPart.attachFile(aFile); } catch (IOException ex) { throw ex; } multipart.addBodyPart(attachPart); } } // sets the multi-part as e-mail's content msg.setContent(multipart); // sends the e-mail Transport.send(msg); } }
If you want grasp a deeper understanding on JavaMail programming, see our JavaMail tutorial.
2. Coding the ConfigUtility class
This class is also compact and straightforward:
package net.codejava.swing.mail; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Properties; /** * A utility class that reads/saves SMTP settings from/to a properties file. * @author www.codejava.net * */ public class ConfigUtility { private File configFile = new File("smtp.properties"); private Properties configProps; public Properties loadProperties() throws IOException { Properties defaultProps = new Properties(); // sets default properties defaultProps.setProperty("mail.smtp.host", "smtp.gmail.com"); defaultProps.setProperty("mail.smtp.port", "587"); defaultProps.setProperty("mail.user", "tom@gmail.com"); defaultProps.setProperty("mail.password", "secret"); defaultProps.setProperty("mail.smtp.starttls.enable", "true"); defaultProps.setProperty("mail.smtp.auth", "true"); configProps = new Properties(defaultProps); // loads properties from file if (configFile.exists()) { InputStream inputStream = new FileInputStream(configFile); configProps.load(inputStream); inputStream.close(); } return configProps; } public void saveProperties(String host, String port, String user, String pass) throws IOException { configProps.setProperty("mail.smtp.host", host); configProps.setProperty("mail.smtp.port", port); configProps.setProperty("mail.user", user); configProps.setProperty("mail.password", pass); configProps.setProperty("mail.smtp.starttls.enable", "true"); configProps.setProperty("mail.smtp.auth", "true"); OutputStream outputStream = new FileOutputStream(configFile); configProps.store(outputStream, "host setttings"); outputStream.close(); } }
This class will be used by the SwingEmailSender and SettingsDialog classes.
3. Coding the SettingsDialog class
The structure of this class is as follows:
public class SettingsDialog extends JDialog { private ConfigUtility configUtil; // GUI components declaration public SettingsDialog(JFrame parent, ConfigUtility configUtil) { setupForm(); loadSettings(); } private void setupForm() { } private void loadSettings() { } private void buttonSaveActionPerformed(ActionEvent event) { } }
Here’s its full code:
package net.codejava.swing.mail; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.util.Properties; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JTextField; /** * Displays a setting form that allows configuring SMTP settings. * @author www.codejava.net * */ public class SettingsDialog extends JDialog { private ConfigUtility configUtil; private JLabel labelHost = new JLabel("Host name: "); private JLabel labelPort = new JLabel("Port number: "); private JLabel labelUser = new JLabel("Username: "); private JLabel labelPass = new JLabel("Password: "); private JTextField textHost = new JTextField(20); private JTextField textPort = new JTextField(20); private JTextField textUser = new JTextField(20); private JTextField textPass = new JTextField(20); private JButton buttonSave = new JButton("Save"); public SettingsDialog(JFrame parent, ConfigUtility configUtil) { super(parent, "SMTP Settings", true); this.configUtil = configUtil; setupForm(); loadSettings(); pack(); setLocationRelativeTo(null); } private void setupForm() { setLayout(new GridBagLayout()); GridBagConstraints constraints = new GridBagConstraints(); constraints.gridx = 0; constraints.gridy = 0; constraints.insets = new Insets(10, 10, 5, 10); constraints.anchor = GridBagConstraints.WEST; add(labelHost, constraints); constraints.gridx = 1; add(textHost, constraints); constraints.gridy = 1; constraints.gridx = 0; add(labelPort, constraints); constraints.gridx = 1; add(textPort, constraints); constraints.gridy = 2; constraints.gridx = 0; add(labelUser, constraints); constraints.gridx = 1; add(textUser, constraints); constraints.gridy = 3; constraints.gridx = 0; add(labelPass, constraints); constraints.gridx = 1; add(textPass, constraints); constraints.gridy = 4; constraints.gridx = 0; constraints.gridwidth = 2; constraints.anchor = GridBagConstraints.CENTER; add(buttonSave, constraints); buttonSave.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { buttonSaveActionPerformed(event); } }); } private void loadSettings() { Properties configProps = null; try { configProps = configUtil.loadProperties(); } catch (IOException ex) { JOptionPane.showMessageDialog(this, "Error reading settings: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } textHost.setText(configProps.getProperty("mail.smtp.host")); textPort.setText(configProps.getProperty("mail.smtp.port")); textUser.setText(configProps.getProperty("mail.user")); textPass.setText(configProps.getProperty("mail.password")); } private void buttonSaveActionPerformed(ActionEvent event) { try { configUtil.saveProperties(textHost.getText(), textPort.getText(), textUser.getText(), textPass.getText()); JOptionPane.showMessageDialog(SettingsDialog.this, "Properties were saved successfully!"); dispose(); } catch (IOException ex) { JOptionPane.showMessageDialog(this, "Error saving properties file: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }
4. Coding the SwingEmailSender class
The structure of this class is as follows:
public class SwingEmailSender extends JFrame { private ConfigUtility configUtil = new ConfigUtility(); // GUI components declaration public SwingEmailSender() { setupMenu(); setupForm(); } private void setupMenu() { } private void setupForm() { } private void buttonSendActionPerformed(ActionEvent event) { } private boolean validateFields() { } public static void main(String[] args) { } }
And following is its full code:
package net.codejava.swing.mail; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import java.util.Properties; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; import javax.swing.UIManager; import net.codejava.swing.JFilePicker; /** * A Swing application that allows sending e-mail messages from a SMTP server. * @author www.codejava.net * */ public class SwingEmailSender extends JFrame { private ConfigUtility configUtil = new ConfigUtility(); private JMenuBar menuBar = new JMenuBar(); private JMenu menuFile = new JMenu("File"); private JMenuItem menuItemSetting = new JMenuItem("Settings.."); private JLabel labelTo = new JLabel("To: "); private JLabel labelSubject = new JLabel("Subject: "); private JTextField fieldTo = new JTextField(30); private JTextField fieldSubject = new JTextField(30); private JButton buttonSend = new JButton("SEND"); private JFilePicker filePicker = new JFilePicker("Attached", "Attach File..."); private JTextArea textAreaMessage = new JTextArea(10, 30); private GridBagConstraints constraints = new GridBagConstraints(); public SwingEmailSender() { super("Swing E-mail Sender Program"); // set up layout setLayout(new GridBagLayout()); constraints.anchor = GridBagConstraints.WEST; constraints.insets = new Insets(5, 5, 5, 5); setupMenu(); setupForm(); pack(); setLocationRelativeTo(null); // center on screen setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private void setupMenu() { menuItemSetting.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { SettingsDialog dialog = new SettingsDialog(SwingEmailSender.this, configUtil); dialog.setVisible(true); } }); menuFile.add(menuItemSetting); menuBar.add(menuFile); setJMenuBar(menuBar); } private void setupForm() { constraints.gridx = 0; constraints.gridy = 0; add(labelTo, constraints); constraints.gridx = 1; constraints.fill = GridBagConstraints.HORIZONTAL; add(fieldTo, constraints); constraints.gridx = 0; constraints.gridy = 1; add(labelSubject, constraints); constraints.gridx = 1; constraints.fill = GridBagConstraints.HORIZONTAL; add(fieldSubject, constraints); constraints.gridx = 2; constraints.gridy = 0; constraints.gridheight = 2; constraints.fill = GridBagConstraints.BOTH; buttonSend.setFont(new Font("Arial", Font.BOLD, 16)); add(buttonSend, constraints); buttonSend.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { buttonSendActionPerformed(event); } }); constraints.gridx = 0; constraints.gridy = 2; constraints.gridheight = 1; constraints.gridwidth = 3; filePicker.setMode(JFilePicker.MODE_OPEN); add(filePicker, constraints); constraints.gridy = 3; constraints.weightx = 1.0; constraints.weighty = 1.0; add(new JScrollPane(textAreaMessage), constraints); } private void buttonSendActionPerformed(ActionEvent event) { if (!validateFields()) { return; } String toAddress = fieldTo.getText(); String subject = fieldSubject.getText(); String message = textAreaMessage.getText(); File[] attachFiles = null; if (!filePicker.getSelectedFilePath().equals("")) { File selectedFile = new File(filePicker.getSelectedFilePath()); attachFiles = new File[] {selectedFile}; } try { Properties smtpProperties = configUtil.loadProperties(); EmailUtility.sendEmail(smtpProperties, toAddress, subject, message, attachFiles); JOptionPane.showMessageDialog(this, "The e-mail has been sent successfully!"); } catch (Exception ex) { JOptionPane.showMessageDialog(this, "Error while sending the e-mail: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } private boolean validateFields() { if (fieldTo.getText().equals("")) { JOptionPane.showMessageDialog(this, "Please enter To address!", "Error", JOptionPane.ERROR_MESSAGE); fieldTo.requestFocus(); return false; } if (fieldSubject.getText().equals("")) { JOptionPane.showMessageDialog(this, "Please enter subject!", "Error", JOptionPane.ERROR_MESSAGE); fieldSubject.requestFocus(); return false; } if (textAreaMessage.getText().equals("")) { JOptionPane.showMessageDialog(this, "Please enter message!", "Error", JOptionPane.ERROR_MESSAGE); textAreaMessage.requestFocus(); return false; } return true; } public static void main(String[] args) { // set look and feel to system dependent try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ex) { ex.printStackTrace(); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SwingEmailSender().setVisible(true); } }); } }
5. Testing the application
Launch the application by executing the class SwingEmailSender. First, we need to specify SMTP settings (if you have not created the smtp.properties file yet). Click File > Settings… to show up the SMTP Settings dialog as follows:
Enter your SMTP account information and click Save, a successful message dialog should appear:
Back to the e-mail form, enter the information as follows:
The attached file is optional, so we can pick one or not. When done, click SEND button to send the e-mail. If everything is going well, then we should get the following message after a few seconds:
In case of error, e.g. the user/password is incorrect, an error message dialog appears:
And thank you for contacting us!
You can download full source code and executable jar file of the application in the attachments section, or clone code from GitHub via this link.
Related Tutorials:
- How to send e-mail with attachment in Java
- Read and write configuration using Properties class in Java
- How to create File picker component in Swing
Other Java Coding Tutorials:
- 10 Common Mistakes Every Beginner Java Programmer Makes
- 10 Java Core Best Practices Every Java Programmer Should Know
- How to become a good programmer? 13 tasks you should practice now
- How to calculate MD5 and SHA hash values in Java
- How to generate random numbers in Java
- Java File Encryption and Decryption Example
Comments
Either password or username is incorrect.
voici l'erreur
javax.mail.AuthenticationFailedException: 535-5.7.8 Username and Password not accepted. Learn more at
535 5.7.8 support.google.com/mail/?p=BadCredentials o15sm31991641wra.93 - gsmtp