BLOG POSTS
JavaMail Example: Send Mail in Java SMTP

JavaMail Example: Send Mail in Java SMTP

JavaMail API is the standard solution for sending emails from Java applications, providing a platform-independent and protocol-independent framework for building mail and messaging apps. Whether you’re building automated notification systems, user registration confirmations, or complex email marketing tools, understanding SMTP integration is essential for modern application development. This guide walks you through practical JavaMail implementation with SMTP, covering everything from basic setup to production-ready configurations with security best practices.

How JavaMail SMTP Works

JavaMail operates through a session-based architecture where you establish an SMTP connection, authenticate with mail servers, and transmit messages using the Simple Mail Transfer Protocol. The API abstracts the underlying SMTP commands while giving you control over message composition, attachments, and delivery options.

The core components include:

  • Session – Represents a mail session with configuration properties
  • Transport – Handles the actual message transmission via SMTP
  • Message – Contains email content, headers, and recipients
  • Authenticator – Manages SMTP server authentication

Modern SMTP servers typically require TLS encryption and authentication, making proper configuration crucial for reliable email delivery.

Setting Up JavaMail Dependencies

First, add JavaMail to your project. For Maven projects:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

For Gradle:

implementation 'com.sun.mail:javax.mail:1.6.2'

If you’re using Java 9+ modules, add this to your module-info.java:

requires java.mail;

Basic SMTP Email Implementation

Here’s a complete working example for sending emails through SMTP:

import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;

public class EmailSender {
    
    public static void sendEmail(String toEmail, String subject, String body) {
        String fromEmail = "your-email@example.com";
        String password = "your-password";
        String smtpHost = "smtp.gmail.com";
        
        Properties props = new Properties();
        props.put("mail.smtp.host", smtpHost);
        props.put("mail.smtp.port", "587");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.ssl.trust", smtpHost);
        
        Authenticator auth = new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(fromEmail, password);
            }
        };
        
        Session session = Session.getInstance(props, auth);
        
        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress(fromEmail));
            message.setRecipients(Message.RecipientType.TO, 
                InternetAddress.parse(toEmail));
            message.setSubject(subject);
            message.setText(body);
            
            Transport.send(message);
            System.out.println("Email sent successfully!");
            
        } catch (MessagingException e) {
            System.err.println("Failed to send email: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        sendEmail("recipient@example.com", 
                 "Test Subject", 
                 "Hello from JavaMail!");
    }
}

Advanced Configuration for Production

Production environments require more robust configuration with proper error handling and security measures:

import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
import java.util.concurrent.TimeUnit;

public class ProductionEmailSender {
    
    private final Session session;
    private final String fromEmail;
    
    public ProductionEmailSender(String smtpHost, int port, String username, String password) {
        this.fromEmail = username;
        
        Properties props = new Properties();
        props.put("mail.smtp.host", smtpHost);
        props.put("mail.smtp.port", String.valueOf(port));
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.starttls.required", "true");
        props.put("mail.smtp.ssl.protocols", "TLSv1.2");
        props.put("mail.smtp.connectiontimeout", "10000");
        props.put("mail.smtp.timeout", "10000");
        props.put("mail.smtp.writetimeout", "10000");
        
        // Connection pooling for better performance
        props.put("mail.smtp.connectionpoolsize", "10");
        props.put("mail.smtp.connectionpooltimeout", "30000");
        
        this.session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
        
        // Enable debug mode for troubleshooting
        session.setDebug(false);
    }
    
    public void sendHtmlEmail(String[] recipients, String subject, String htmlContent) 
            throws MessagingException {
        
        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress(fromEmail));
        
        // Handle multiple recipients
        InternetAddress[] addresses = new InternetAddress[recipients.length];
        for (int i = 0; i < recipients.length; i++) {
            addresses[i] = new InternetAddress(recipients[i]);
        }
        message.setRecipients(Message.RecipientType.TO, addresses);
        
        message.setSubject(subject);
        message.setContent(htmlContent, "text/html; charset=utf-8");
        message.setSentDate(new java.util.Date());
        
        // Add custom headers
        message.setHeader("X-Mailer", "JavaMail Production Sender");
        message.setHeader("X-Priority", "3");
        
        Transport.send(message);
    }
}

SMTP Provider Comparison

Different SMTP providers have varying configurations and limitations:

Provider SMTP Host Port (TLS) Daily Limit Authentication
Gmail smtp.gmail.com 587 500 OAuth2/App Password
Outlook smtp-mail.outlook.com 587 300 Username/Password
Yahoo smtp.mail.yahoo.com 587 500 App Password Required
SendGrid smtp.sendgrid.net 587 100/day (free) API Key
Amazon SES email-smtp.region.amazonaws.com 587 200/day (free) SMTP Credentials

Sending Emails with Attachments

Multipart messages allow you to send attachments alongside text content:

public void sendEmailWithAttachment(String toEmail, String subject, 
                                   String body, String filePath) throws MessagingException {
    
    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress(fromEmail));
    message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail));
    message.setSubject(subject);
    
    // Create multipart message
    Multipart multipart = new MimeMultipart();
    
    // Text part
    BodyPart textPart = new MimeBodyPart();
    textPart.setText(body);
    multipart.addBodyPart(textPart);
    
    // Attachment part
    BodyPart attachmentPart = new MimeBodyPart();
    DataSource source = new FileDataSource(filePath);
    attachmentPart.setDataHandler(new DataHandler(source));
    attachmentPart.setFileName(new File(filePath).getName());
    multipart.addBodyPart(attachmentPart);
    
    message.setContent(multipart);
    Transport.send(message);
}

Common Issues and Troubleshooting

Here are the most frequent problems developers encounter with JavaMail SMTP:

  • Authentication Failed (535) - Often caused by incorrect credentials or missing app passwords for Gmail/Yahoo
  • Connection Timeout - Firewall blocking SMTP ports or incorrect server settings
  • SSL/TLS Handshake Failure - Outdated Java versions or restrictive SSL protocols
  • Message Rejected (550) - Invalid recipient addresses or spam filtering

Enable debug mode to troubleshoot connection issues:

session.setDebug(true);

// Add this for detailed SSL debugging
System.setProperty("javax.net.debug", "ssl:handshake");

For Gmail users experiencing authentication issues, create an App Password instead of using your regular password:

// Gmail-specific configuration
props.put("mail.smtp.ssl.protocols", "TLSv1.2");
props.put("mail.smtp.ssl.ciphersuites", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256");

Real-World Use Cases and Applications

JavaMail SMTP integration shines in several practical scenarios:

  • User Registration Systems - Send welcome emails and email verification links
  • E-commerce Platforms - Order confirmations, shipping notifications, and receipts
  • Monitoring Systems - Alert notifications for server issues or application errors
  • Content Management - Automated reports, newsletter distribution, and user notifications
  • Enterprise Applications - Workflow notifications, approval requests, and system updates

For high-volume applications running on VPS environments or dedicated servers, consider implementing connection pooling and message queuing:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class BatchEmailSender {
    private final ExecutorService executor;
    private final BlockingQueue<EmailTask> emailQueue;
    private final ProductionEmailSender emailSender;
    
    public BatchEmailSender(ProductionEmailSender sender, int threadPoolSize) {
        this.emailSender = sender;
        this.executor = Executors.newFixedThreadPool(threadPoolSize);
        this.emailQueue = new LinkedBlockingQueue<>();
        
        // Start worker threads
        for (int i = 0; i < threadPoolSize; i++) {
            executor.submit(this::processEmailQueue);
        }
    }
    
    public void queueEmail(String[] recipients, String subject, String content) {
        emailQueue.offer(new EmailTask(recipients, subject, content));
    }
    
    private void processEmailQueue() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                EmailTask task = emailQueue.take();
                emailSender.sendHtmlEmail(task.recipients, task.subject, task.content);
                Thread.sleep(100); // Rate limiting
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            } catch (Exception e) {
                System.err.println("Failed to send email: " + e.getMessage());
            }
        }
    }
    
    private static class EmailTask {
        final String[] recipients;
        final String subject;
        final String content;
        
        EmailTask(String[] recipients, String subject, String content) {
            this.recipients = recipients;
            this.subject = subject;
            this.content = content;
        }
    }
}

Best Practices and Security Considerations

Follow these guidelines for production-ready email systems:

  • Use Environment Variables - Never hardcode credentials in source code
  • Implement Rate Limiting - Respect SMTP provider limits to avoid blacklisting
  • Validate Email Addresses - Use proper regex patterns or validation libraries
  • Handle Failures Gracefully - Implement retry logic with exponential backoff
  • Log Email Activities - Track sent emails for debugging and compliance
  • Use Connection Pooling - Reuse SMTP connections for better performance

Security configuration example:

// Environment-based configuration
public class SecureEmailConfig {
    private static final String SMTP_HOST = System.getenv("SMTP_HOST");
    private static final String SMTP_USER = System.getenv("SMTP_USER");
    private static final String SMTP_PASS = System.getenv("SMTP_PASS");
    private static final int SMTP_PORT = Integer.parseInt(
        System.getenv().getOrDefault("SMTP_PORT", "587"));
    
    public static Properties getSecureProperties() {
        Properties props = new Properties();
        props.put("mail.smtp.host", SMTP_HOST);
        props.put("mail.smtp.port", SMTP_PORT);
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.starttls.required", "true");
        props.put("mail.smtp.ssl.protocols", "TLSv1.2 TLSv1.3");
        
        // Prevent SMTP injection
        props.put("mail.smtp.send.partial", "false");
        props.put("mail.smtp.quitwait", "false");
        
        return props;
    }
}

For comprehensive JavaMail documentation and advanced features, refer to the official JavaMail API documentation. The Eclipse Foundation's Jakarta Mail project provides updated specifications and examples for modern Java applications.

Performance-wise, JavaMail can handle approximately 100-500 emails per minute depending on your server configuration and SMTP provider limitations. For applications requiring higher throughput, consider dedicated email services or implementing message queuing systems with frameworks like Apache Kafka or RabbitMQ.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

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