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:

Swing E-mail Sender program

The SMTP settings can be configured in a dialog which is accessible from menu File > Settings… as follows:

SMTP settings dialog

Work flow of the application is explained in the following diagram:

Swing email program workflow

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:

Swing Email Sender Program Class diagram

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:

Settings dialog

Enter your SMTP account information and click Save, a successful message dialog should appear:

save settings success

Back to the e-mail form, enter the information as follows:

test sending e-mail

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:

email sent success

In case of error, e.g. the user/password is incorrect, an error message dialog appears:

sent email error

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:

 

Other Java Coding Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.



Attachments:
Download this file (SwingEmailSender.zip)SwingEmailSender.zip[Full source code and executable jar file]513 kB

Add comment

   


Comments 

#23Meer2022-10-05 17:06
testing for sending email using java swing
Quote
#22Nam2022-05-23 21:48
To prasen: link to download the sample project here: www.codejava.net/download-attachment?fid=178
Quote
#21prasen2022-05-23 00:54
send me this code file
Quote
#20Nam2021-03-29 22:25
Hi Damien,
Either password or username is incorrect.
Quote
#19Damien2021-03-29 07:19
J'ai l'erreur suivante alors que mon email et mot de passe sont valide
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
Quote