JavaMailの例 – SMTPを使用してJavaでメールを送信する方法

今日は、Javaプログラムでメールを送信するJavaMailの例を見てみましょう。 メールの送信は、実生活のアプリケーションでの一般的なタスクの1つであり、そのためJavaは強力なJavaMail APIを提供しています。このAPIを使用してSMTPサーバーを介してメールを送信できます。JavaMail APIは、メールの送信にTLSおよびSSL認証の両方をサポートしています。

JavaMailの例

今日は、SMTPサーバーを使用してメールを送信するためのJavaMail APIの使用方法、認証なしのTLSおよびSSL認証、およびメール本文に添付ファイルを送信し、画像を添付して使用する方法を学びます。TLSおよびSSL認証では、両方をサポートするため、GMail SMTPサーバーを使用しています。プロジェクトの要件に応じて、Javaメールサーバーを選択することもできます。JavaMail APIは標準のJDKの一部ではないため、公式ウェブサイト、すなわちJavaMailホームページからダウンロードする必要があります。JavaMailリファレンス実装の最新バージョンをダウンロードし、プロジェクトのビルドパスに含めます。jarファイルの名前はjavax.mail.jarになります。Mavenベースのプロジェクトを使用している場合は、プロジェクトに以下の依存関係を追加するだけです。

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

メールを送信するJavaプログラムには以下のステップが含まれています:

  1. javax.mail.Session オブジェクトを作成する
  2. javax.mail.internet.MimeMessage オブジェクトを作成する際に、受信者のメールアドレス、メールの件名、返信先メールアドレス、メール本文、添付ファイルなど、このオブジェクトに異なるプロパティを設定する必要があります。
  3. javax.mail.Transport を使用してメールメッセージを送信します。

セッションを作成するロジックは、SMTP サーバーの種類によって異なります。たとえば、SMTP サーバーが認証を必要としない場合、いくつかの簡単なプロパティを使用してセッションオブジェクトを作成できますが、TLS または SSL 認証が必要な場合は、作成するロジックが異なります。したがって、異なる SMTP サーバーでこのユーティリティメソッドを使用します。

JavaMail の例題プログラム

単一のメソッドを持つ EmailUtil クラスを以下に示します。このメソッドでは、javax.mail.Session およびその他の必要なフィールドが引数として必要です。単純にするために、一部の引数はハードコードされていますが、これを拡張して引数を渡したり、構成ファイルから読み取ったりできます。

package com.journaldev.mail;

import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class EmailUtil {

	/**
	 * Utility method to send simple HTML email
	 * @param session
	 * @param toEmail
	 * @param subject
	 * @param body
	 */
	public static void sendEmail(Session session, String toEmail, String subject, String body){
		try
	    {
	      MimeMessage msg = new MimeMessage(session);
	      // メッセージヘッダーを設定します。
	      msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	      msg.addHeader("format", "flowed");
	      msg.addHeader("Content-Transfer-Encoding", "8bit");

	      msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	      msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	      msg.setSubject(subject, "UTF-8");

	      msg.setText(body, "UTF-8");

	      msg.setSentDate(new Date());

	      msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      System.out.println("Message is ready");
    	  Transport.send(msg);  

	      System.out.println("EMail Sent Successfully!!");
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	}
}

MimeMessage でいくつかのヘッダープロパティを設定していることに注意してください。これらは、メールクライアントがメールメッセージを適切に表示およびレンダリングするために使用されます。プログラムの残りは単純で理解しやすいです。これで、認証なしでメールを送信するプログラムを作成しましょう。

SMTPを使用した認証なしでJavaでメールを送信する

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Session;

public class SimpleEmail {
	
	public static void main(String[] args) {
		
	    System.out.println("SimpleEmail Start");
		
	    String smtpHostServer = "smtp.example.com";
	    String emailID = "[email protected]";
	    
	    Properties props = System.getProperties();

	    props.put("mail.smtp.host", smtpHostServer);

	    Session session = Session.getInstance(props, null);
	    
	    EmailUtil.sendEmail(session, emailID,"SimpleEmail Testing Subject", "SimpleEmail Testing Body");
	}

}

注意:Propertiesオブジェクトを渡してSessionオブジェクトを取得するためにSession.getInstance()を使用しています。SMTPサーバーホストをmail.smtp.hostプロパティに設定する必要があります。SMTPサーバーがデフォルトポート(25)で実行されていない場合は、mail.smtp.portプロパティも設定する必要があります。認証なしのSMTPサーバーを使用してこのプログラムを実行し、受信者のメールIDを自分のメールIDに設定すると、すぐにメールが届きます。プログラムは理解しやすく、うまく機能しますが、実際の生活ではほとんどのSMTPサーバーがTLSやSSL認証などの認証方式を使用しています。したがって、これらの認証プロトコル用のSessionオブジェクトを作成する方法を見ていきます。

TLS認証を使用したJava SMTPでのメール送信

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;

public class TLSEmail {

	/**
	   Outgoing Mail (SMTP) Server
	   requires TLS or SSL: smtp.gmail.com (use authentication)
	   Use Authentication: Yes
	   Port for TLS/STARTTLS: 587
	 */
	public static void main(String[] args) {
		final String fromEmail = "[email protected]"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "[email protected]"; // can be any email id 
		
		System.out.println("TLSEmail Start");
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
		props.put("mail.smtp.port", "587"); //TLS Port
		props.put("mail.smtp.auth", "true"); //enable authentication
		props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
		
                //Session.getInstance引数に渡すためのAuthenticatorオブジェクトを作成する
		Authenticator auth = new Authenticator() {
			//getPasswordAuthenticationメソッドをオーバーライドする
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromEmail, password);
			}
		};
		Session session = Session.getInstance(props, auth);
		
		EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body");
		
	}

	
}

私が利用可能なGmail SMTPサーバーを使用しているので、上記のプログラムで正しい変数を設定して自分で実行できます。信じてください、うまく動作します! 🙂

SSL認証を使用したJava SMTPの例

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;

public class SSLEmail {

	/**
	   Outgoing Mail (SMTP) Server
	   requires TLS or SSL: smtp.gmail.com (use authentication)
	   Use Authentication: Yes
	   Port for SSL: 465
	 */
	public static void main(String[] args) {
		final String fromEmail = "[email protected]"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "[email protected]"; // can be any email id 
		
		System.out.println("SSLEmail Start");
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
		props.put("mail.smtp.socketFactory.port", "465"); //SSL Port
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory"); //SSL Factory Class
		props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication
		props.put("mail.smtp.port", "465"); //SMTP Port
		
		Authenticator auth = new Authenticator() {
			//getPasswordAuthenticationメソッドをオーバーライド
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromEmail, password);
			}
		};
		
		Session session = Session.getDefaultInstance(props, auth);
		System.out.println("Session created");
	        EmailUtil.sendEmail(session, toEmail,"SSLEmail Testing Subject", "SSLEmail Testing Body");

	        EmailUtil.sendAttachmentEmail(session, toEmail,"SSLEmail Testing Subject with Attachment", "SSLEmail Testing Body with Attachment");

	        EmailUtil.sendImageEmail(session, toEmail,"SSLEmail Testing Subject with Image", "SSLEmail Testing Body with Image");

	}

}

プログラムはTLS認証とほぼ同じですが、いくつかのプロパティが異なります。EmailUtilクラスから他のメソッドを呼び出して添付ファイルや画像を電子メールで送信していますが、まだそれらを定義していません。実際には、後で示すためにそれらを保持し、チュートリアルの開始時にシンプルに保っています。

JavaMailの例 – 添付ファイル付きでJavaでメールを送信する

ファイルを添付して送信するには、javax.mail.internet.MimeBodyPartjavax.mail.internet.MimeMultipartのオブジェクトを作成する必要があります。まず、メールのテキストメッセージのボディパートを追加し、次にファイルをマルチパートボディの第二部分に添付するためにFileDataSourceを使用します。メソッドは次のようになります。

/**
 * Utility method to send email with attachment
 * @param session
 * @param toEmail
 * @param subject
 * @param body
 */
public static void sendAttachmentEmail(Session session, String toEmail, String subject, String body){
	try{
         MimeMessage msg = new MimeMessage(session);
         msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	     msg.addHeader("format", "flowed");
	     msg.addHeader("Content-Transfer-Encoding", "8bit");
	      
	     msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	     msg.setSubject(subject, "UTF-8");

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // メッセージボディパートを作成
         BodyPart messageBodyPart = new MimeBodyPart();

         // メッセージを埋める
         messageBodyPart.setText(body);
         
         // 添付ファイル用のマルチパートメッセージを作成
         Multipart multipart = new MimeMultipart();

         // テキストメッセージパートを設定
         multipart.addBodyPart(messageBodyPart);

         // 第二部分は添付ファイル
         messageBodyPart = new MimeBodyPart();
         String filename = "abc.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // 完全なメッセージパーツを送信
         msg.setContent(multipart);

         // メッセージを送信
         Transport.send(msg);
         System.out.println("EMail Sent Successfully with attachment!!");
      }catch (MessagingException e) {
         e.printStackTrace();
      } catch (UnsupportedEncodingException e) {
		 e.printStackTrace();
	}
}

プログラムは最初は複雑に見えるかもしれませんが、実際にはシンプルです。テキストメッセージ用のボディパートと添付ファイル用の別のボディパートを作成し、それらをマルチパートに追加するだけです。この方法を拡張して複数のファイルを添付することもできます。

JavaMailの例 – 画像を添付してJavaでメールを送信する

HTMLボディメッセージを作成できるので、画像ファイルがサーバーの場所にある場合はimg要素を使用してメッセージ内でそれらを表示できます。しかし、時々、メールに画像添付ファイルがあり、またメールメッセージで使用されているのを見たことがあるかもしれません。トリックは、画像ファイルを他の添付ファイルと同様に添付し、Content-IDヘッダーを画像ファイルに設定し、次に同じコンテンツIDをメールメッセージ本文で<img src='cid:image_id'>として使用することです。

/**
 * Utility method to send image in email body
 * @param session
 * @param toEmail
 * @param subject
 * @param body
 */
public static void sendImageEmail(Session session, String toEmail, String subject, String body){
	try{
         MimeMessage msg = new MimeMessage(session);
         msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	     msg.addHeader("format", "flowed");
	     msg.addHeader("Content-Transfer-Encoding", "8bit");
	      
	     msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	     msg.setSubject(subject, "UTF-8");

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // メッセージボディパートを作成
         BodyPart messageBodyPart = new MimeBodyPart();

         messageBodyPart.setText(body);
         
         // 添付ファイル用のマルチパートメッセージを作成
         Multipart multipart = new MimeMultipart();

         // テキストメッセージパートを設定
         multipart.addBodyPart(messageBodyPart);

         // 2番目のパートは画像の添付ファイルです
         messageBodyPart = new MimeBodyPart();
         String filename = "image.png";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         // トリックはここでContent-IDヘッダーを追加することです
         messageBodyPart.setHeader("Content-ID", "image_id");
         multipart.addBodyPart(messageBodyPart);

         // メール本文で画像を表示するための3番目のパート
         messageBodyPart = new MimeBodyPart();
         messageBodyPart.setContent("

Attached Image

" + "", "text/html"); multipart.addBodyPart(messageBodyPart); // マルチパートメッセージをメールメッセージに設定 msg.setContent(multipart); // メッセージを送信 Transport.send(msg); System.out.println("EMail Sent Successfully with image!!"); }catch (MessagingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }

JavaMail API トラブルシューティングのヒント

  1. java.net.UnknownHostExceptionは、システムがSMTPサーバーのIPアドレスを解決できないときに発生します。これは、間違っているか、ネットワークからアクセスできない可能性があります。例えば、GmailのSMTPサーバーはsmtp.gmail.comであり、smtp.google.comを使用するとこの例外が発生します。ホスト名が正しい場合は、コマンドラインを使用してサーバーにpingして、システムからアクセスできることを確認してください。

    pankaj@Pankaj:~/CODE$ ping smtp.gmail.com
    PING gmail-smtp-msa.l.google.com (74.125.129.108): 56 data bytes
    64 bytes from 74.125.129.108: icmp_seq=0 ttl=46 time=38.308 ms
    64 bytes from 74.125.129.108: icmp_seq=1 ttl=46 time=42.247 ms
    64 bytes from 74.125.129.108: icmp_seq=2 ttl=46 time=38.164 ms
    64 bytes from 74.125.129.108: icmp_seq=3 ttl=46 time=53.153 ms
    
  2. プログラムがTransport send()メソッド呼び出しで停止している場合は、SMTPポートが正しいことを確認してください。正しい場合は、telnetを使用してマシンからアクセス可能であることを確認し、以下のような出力が得られます。

    pankaj@Pankaj:~/CODE$ telnet smtp.gmail.com 587
    Trying 2607:f8b0:400e:c02::6d...
    Connected to gmail-smtp-msa.l.google.com.
    Escape character is '^]'.
    220 mx.google.com ESMTP sx8sm78485186pab.5 - gsmtp
    HELO
    250 mx.google.com at your service
    

これで、JavaプログラムでSMTPサーバーを使用してメールを送信するJavaMailの例に関するすべてのニーズが解決されることを願っています。

Source:
https://www.digitalocean.com/community/tutorials/javamail-example-send-mail-in-java-smtp