google-site-verification: google61fe8ba583a51912.html
Building a Desktop SMTP Email Sender with Java Swing

Sending emails programmatically is a common requirement for many desktop applications, from newsletter tools to automated notification systems. While Java provides the robust javax.mail API (now Jakarta Mail) for handling email protocols, combining it with a Swing GUI creates a user-friendly desktop utility.

This article guides you through building a fully-featured SMTP email client with a graphical user interface in Java, supporting attachments, HTML content, and secure authentication.


Architecture and Technologies

Our application will be built on two main pillars:

  1. Frontend (GUI): Java Swing for the user interface.
  2. Backend (Email): Jakarta Mail (formerly JavaMail) for SMTP communication.

Project Setup: Dependencies

You need to add the Jakarta Mail dependency to your project.

Maven:

<dependencies> <dependency> <groupId>com.sun.mail</groupId> <artifactId>jakarta.mail</artifactId> <version>2.0.1</version> </dependency> <!-- Also ensure you have the Jakarta Activation API --> <dependency> <groupId>com.sun.activation</groupId> <artifactId>jakarta.activation</artifactId> <version>2.0.1</version> </dependency> </dependencies>

Gradle:

dependencies { implementation 'com.sun.mail:jakarta.mail:2.0.1' implementation 'com.sun.activation:jakarta.activation:2.0.1' }

Building the GUI: A Step-by-Step Approach

We'll create a form with fields for all essential email components and a console for feedback.

Main Application Frame

import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.io.File; public class EmailSenderGUI extends JFrame { // Form components private JTextField smtpHostField, smtpPortField, usernameField; private JPasswordField passwordField; private JCheckBox authCheckBox, tlsCheckBox; private JTextField toField, ccField, bccField, subjectField; private JTextArea messageArea; private JButton attachButton, sendButton, clearButton; private JList<File> attachmentList; private DefaultListModel<File> attachmentListModel; private JTextArea consoleArea; public EmailSenderGUI() { initializeGUI(); } private void initializeGUI() { setTitle("Java SMTP Email Sender"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout(10, 10)); // Create main panels JPanel serverPanel = createServerPanel(); JPanel recipientPanel = createRecipientPanel(); JPanel messagePanel = createMessagePanel(); JPanel attachmentPanel = createAttachmentPanel(); JPanel buttonPanel = createButtonPanel(); JPanel consolePanel = createConsolePanel(); // Arrange panels in the frame JPanel northPanel = new JPanel(new GridLayout(3, 1, 5, 5)); northPanel.add(serverPanel); northPanel.add(recipientPanel); northPanel.add(attachmentPanel); add(northPanel, BorderLayout.NORTH); add(messagePanel, BorderLayout.CENTER); add(buttonPanel, BorderLayout.SOUTH); add(consolePanel, BorderLayout.SOUTH); // Adjust layout pack(); setSize(800, 700); setLocationRelativeTo(null); // Center the window }

Server Configuration Panel

 private JPanel createServerPanel() { JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5)); panel.setBorder(BorderFactory.createTitledBorder("SMTP Server Configuration")); // Initialize components smtpHostField = new JTextField("smtp.gmail.com"); smtpPortField = new JTextField("587"); usernameField = new JTextField(); passwordField = new JPasswordField(); authCheckBox = new JCheckBox("Require Authentication", true); tlsCheckBox = new JCheckBox("Use STARTTLS", true); // Add components to panel panel.add(new JLabel("SMTP Host:")); panel.add(smtpHostField); panel.add(new JLabel("SMTP Port:")); panel.add(smtpPortField); panel.add(new JLabel("Username:")); panel.add(usernameField); panel.add(new JLabel("Password:")); panel.add(passwordField); panel.add(authCheckBox); panel.add(tlsCheckBox); return panel; }

Recipient Information Panel

 private JPanel createRecipientPanel() { JPanel panel = new JPanel(new GridLayout(0, 2, 5, 5)); panel.setBorder(BorderFactory.createTitledBorder("Recipients")); toField = new JTextField(); ccField = new JTextField(); bccField = new JTextField(); subjectField = new JTextField(); panel.add(new JLabel("To (comma-separated):")); panel.add(toField); panel.add(new JLabel("CC (comma-separated):")); panel.add(ccField); panel.add(new JLabel("BCC (comma-separated):")); panel.add(bccField); panel.add(new JLabel("Subject:")); panel.add(subjectField); return panel; }

Message Composition Panel

 private JPanel createMessagePanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createTitledBorder("Message")); messageArea = new JTextArea(15, 50); messageArea.setLineWrap(true); messageArea.setWrapStyleWord(true); JScrollPane scrollPane = new JScrollPane(messageArea); panel.add(scrollPane, BorderLayout.CENTER); return panel; }

Attachment Management Panel

 private JPanel createAttachmentPanel() { JPanel panel = new JPanel(new BorderLayout(5, 5)); panel.setBorder(BorderFactory.createTitledBorder("Attachments")); attachmentListModel = new DefaultListModel<>(); attachmentList = new JList<>(attachmentListModel); JScrollPane listScrollPane = new JScrollPane(attachmentList); attachButton = new JButton("Add Attachment"); JButton removeButton = new JButton("Remove Selected"); attachButton.addActionListener(this::addAttachment); removeButton.addActionListener(this::removeAttachment); JPanel buttonPanel = new JPanel(); buttonPanel.add(attachButton); buttonPanel.add(removeButton); panel.add(listScrollPane, BorderLayout.CENTER); panel.add(buttonPanel, BorderLayout.SOUTH); return panel; } private void addAttachment(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); fileChooser.setMultiSelectionEnabled(true); int result = fileChooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { File[] files = fileChooser.getSelectedFiles(); for (File file : files) { if (!attachmentListModel.contains(file)) { attachmentListModel.addElement(file); } } } } private void removeAttachment(ActionEvent e) { int[] selectedIndices = attachmentList.getSelectedIndices(); for (int i = selectedIndices.length - 1; i >= 0; i--) { attachmentListModel.remove(selectedIndices[i]); } }

Action Buttons and Console

 private JPanel createButtonPanel() { JPanel panel = new JPanel(new FlowLayout()); sendButton = new JButton("Send Email"); clearButton = new JButton("Clear All"); sendButton.addActionListener(this::sendEmail); clearButton.addActionListener(this::clearAll); panel.add(sendButton); panel.add(clearButton); return panel; } private JPanel createConsolePanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBorder(BorderFactory.createTitledBorder("Console Output")); consoleArea = new JTextArea(8, 60); consoleArea.setEditable(false); consoleArea.setBackground(Color.BLACK); consoleArea.setForeground(Color.GREEN); consoleArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); JScrollPane scrollPane = new JScrollPane(consoleArea); panel.add(scrollPane, BorderLayout.CENTER); return panel; } private void clearAll(ActionEvent e) { toField.setText(""); ccField.setText(""); bccField.setText(""); subjectField.setText(""); messageArea.setText(""); attachmentListModel.clear(); consoleArea.setText(""); } private void log(String message) { consoleArea.append(message + "\n"); consoleArea.setCaretPosition(consoleArea.getDocument().getLength()); // Auto-scroll }

The Email Sending Engine

This is the core functionality that uses Jakarta Mail to send emails.

 private void sendEmail(ActionEvent e) { // Run in a separate thread to keep GUI responsive SwingWorker<Boolean, String> worker = new SwingWorker<>() { @Override protected Boolean doInBackground() throws Exception { try { publish("Starting email sending process..."); // Validate required fields if (toField.getText().trim().isEmpty()) { publish("ERROR: No recipients specified."); return false; } // Get SMTP properties java.util.Properties props = new java.util.Properties(); props.put("mail.smtp.auth", String.valueOf(authCheckBox.isSelected())); props.put("mail.smtp.starttls.enable", String.valueOf(tlsCheckBox.isSelected())); props.put("mail.smtp.host", smtpHostField.getText()); props.put("mail.smtp.port", smtpPortField.getText()); // For debugging props.put("mail.debug", "true"); // Get session jakarta.mail.Session session; if (authCheckBox.isSelected()) { session = jakarta.mail.Session.getInstance(props, new jakarta.mail.Authenticator() { @Override protected jakarta.mail.PasswordAuthentication getPasswordAuthentication() { return new jakarta.mail.PasswordAuthentication( usernameField.getText(), new String(passwordField.getPassword()) ); } }); } else { session = jakarta.mail.Session.getInstance(props); } // Create message jakarta.mail.Message message = new jakarta.mail.internet.MimeMessage(session); message.setFrom(new jakarta.mail.internet.InternetAddress(usernameField.getText())); // Set recipients message.setRecipients(jakarta.mail.Message.RecipientType.TO, jakarta.mail.internet.InternetAddress.parse(toField.getText())); if (!ccField.getText().trim().isEmpty()) { message.setRecipients(jakarta.mail.Message.RecipientType.CC, jakarta.mail.internet.InternetAddress.parse(ccField.getText())); } if (!bccField.getText().trim().isEmpty()) { message.setRecipients(jakarta.mail.Message.RecipientType.BCC, jakarta.mail.internet.InternetAddress.parse(bccField.getText())); } message.setSubject(subjectField.getText()); // Create multipart message for text and attachments jakarta.mail.Multipart multipart = new jakarta.mail.internet.MimeMultipart(); // Create text part jakarta.mail.BodyPart messageBodyPart = new jakarta.mail.internet.MimeBodyPart(); String messageText = messageArea.getText(); // Check if message contains HTML if (messageText.trim().startsWith("<html>")) { messageBodyPart.setContent(messageText, "text/html; charset=utf-8"); } else { messageBodyPart.setText(messageText); } multipart.addBodyPart(messageBodyPart); // Add attachments for (int i = 0; i < attachmentListModel.size(); i++) { File file = attachmentListModel.getElementAt(i); publish("Attaching file: " + file.getName()); messageBodyPart = new jakarta.mail.internet.MimeBodyPart(); messageBodyPart.setDataHandler( new jakarta.activation.DataHandler( new jakarta.activation.FileDataSource(file) ) ); messageBodyPart.setFileName(file.getName()); multipart.addBodyPart(messageBodyPart); } // Set the complete message parts message.setContent(multipart); // Send message publish("Sending email..."); jakarta.mail.Transport.send(message); publish("SUCCESS: Email sent successfully!"); return true; } catch (Exception ex) { publish("ERROR: " + ex.getMessage()); ex.printStackTrace(); return false; } } @Override protected void process(java.util.List<String> chunks) { for (String message : chunks) { log(message); } } @Override protected void done() { sendButton.setEnabled(true); try { Boolean success = get(); if (success) { JOptionPane.showMessageDialog(EmailSenderGUI.this, "Email sent successfully!", "Success", JOptionPane.INFORMATION_MESSAGE); } } catch (Exception ex) { log("ERROR in worker thread: " + ex.getMessage()); } } }; sendButton.setEnabled(false); worker.execute(); }

Main Method

 public static void main(String[] args) { // Set system look and feel try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel()); } catch (Exception e) { e.printStackTrace(); } SwingUtilities.invokeLater(() -> { new EmailSenderGUI().setVisible(true); }); } }

Configuration for Popular Email Providers

Gmail:

  • SMTP Host: smtp.gmail.com
  • Port: 587 (TLS) or 465 (SSL)
  • Requires "App Password" if 2-factor authentication is enabled

Outlook/Office 365:

  • SMTP Host: smtp.office365.com
  • Port: 587
  • Requires authentication

Yahoo Mail:

  • SMTP Host: smtp.mail.yahoo.com
  • Port: 587
  • Requires authentication

Security Considerations

  1. Password Storage: The current implementation stores passwords in memory only during the session. For production applications, consider using secure credential storage.
  2. SSL/TLS: Always use TLS (STARTTLS) for secure communication.
  3. Input Validation: Validate all user inputs to prevent injection attacks.
  4. File Security: Validate attachment types and sizes to prevent security risks.

Conclusion

This SMTP Email Sender GUI provides a solid foundation for a desktop email utility. You can extend it with features like:

  • Email templates
  • Contact list integration
  • Rich text editing for HTML emails
  • Batch sending capabilities
  • SSL certificate handling
  • Logging and sent items history

The combination of Swing for the interface and Jakarta Mail for the email functionality creates a powerful, self-contained application that demonstrates several important Java concepts including GUI development, network communication, and multi-threading with SwingWorker.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper