مثال JavaMail – إرسال بريد في جافا باستخدام SMTP

اليوم سنلقي نظرة على مثال JavaMail لإرسال البريد الإلكتروني في برامج Java. إرسال الرسائل الإلكترونية هو واحد من المهام الشائعة في تطبيقات الحياة الحقيقية، ولهذا السبب توفر Java واجهة برمجة التطبيقات JavaMail API القوية التي يمكننا استخدامها لإرسال الرسائل الإلكترونية باستخدام خادم SMTP. تدعم JavaMail API كل من مصادقة TLS و SSL لإرسال الرسائل الإلكترونية.

مثال JavaMail

اليوم سنتعلم كيفية استخدام JavaMail API لإرسال الرسائل الإلكترونية باستخدام خادم SMTP بدون مصادقة، ومع مصادقة TLS و SSL، وكيفية إرفاق المرفقات واستخدام الصور في جسم البريد الإلكتروني. بالنسبة لمصادقة TLS و SSL، أستخدم خادم SMTP Gmail لأنه يدعم كلاً منهما. يمكنك أيضًا اختيار الانتقال إلى خادم بريد Java Java mail server وفقًا لاحتياجات مشروعك. JavaMail API ليست جزءًا من JDK القياسي، لذا ستحتاج إلى تنزيلها من موقعها الرسمي أي JavaMail Home Page. قم بتنزيل أحدث إصدار من تنفيذ الإشارة البريدية لـ JavaMail وقم بتضمينه في مسار بناء مشروعك. سيكون اسم ملف الجرة 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 بدون مصادقة

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");
	}

}

لاحظ أنني استخدمت Session.getInstance() للحصول على كائن الجلسة عن طريق تمرير كائن الخصائص. نحتاج إلى ضبط خاصية mail.smtp.host بمضيف خادم SMTP. إذا كان خادم SMTP لا يعمل على المنفذ الافتراضي (25)، فيجب أيضًا ضبط خاصية mail.smtp.port. قم بتشغيل هذا البرنامج مع خادم SMTP بدون مصادقة وضبط عنوان البريد الإلكتروني للمستلم كعنوان بريدك الإلكتروني وستحصل على البريد الإلكتروني في وقت قصير. البرنامج سهل الفهم ويعمل بشكل جيد، ولكن في الحياة الواقعية يستخدم معظم خوادم SMTP نوعًا ما من المصادقة مثل مصادقة TLS أو SSL. لذا سنرى الآن كيفية إنشاء كائن الجلسة لهذه البروتوكولات المصادقة.

إرسال بريد إلكتروني في جافا SMTP مع مصادقة TLS

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
		
                //إنشاء كائن Authenticator لتمريره كوسيط في وسيط Session.getInstance
		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");
		
	}

	
}

نظرًا لأنني استخدمت خادم SMTP لـ GMail الذي يمكن الوصول إليه من الجميع، يمكنك ضبط المتغيرات الصحيحة في البرنامج أعلاه وتشغيله بنفسك. صدقني، يعمل!! 🙂

مثال Java SMTP مع المصادقة SSL

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 – إرسال بريد في جافا مع مرفق

لإرسال ملف كمرفق، نحتاج إلى إنشاء كائن من javax.mail.internet.MimeBodyPart و javax.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 – إرسال بريد إلكتروني في جافا مع صورة

نظرًا لأنه يمكننا إنشاء جسم رسالة HTML، إذا كان ملف الصورة موجودًا في مكان ما على الخادم يمكننا استخدام عنصر img لعرضها في الرسالة. ولكن في بعض الأحيان نريد إرفاق الصورة في البريد الإلكتروني واستخدامها في جسم البريد الإلكتروني نفسه. يجب أن تكون قد رأيت العديد من الرسائل الإلكترونية التي تحتوي على مرفقات صور ويتم استخدامها أيضًا في رسالة البريد الإلكتروني. الحيلة تكمن في إرفاق ملف الصورة مثل أي مرفق آخر ثم ضبط رأس Content-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);

         // الجزء الثاني هو مرفق الصورة
         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);

         // الجزء الثالث لعرض الصورة في جسم البريد الإلكتروني
         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(); } }

نصائح ل solución de problemas بواجهة برمجة تطبيقات JavaMail

  1. java.net.UnknownHostException يأتي عندما لا يكون نظامك قادرًا على حل عنوان IP لخادم SMTP، قد يكون خاطئًا أو غير متاح من شبكتك. على سبيل المثال، خادم SMTP لـ GMail هو smtp.gmail.com وإذا استخدمت smtp.google.com، سأحصل على هذا الاستثناء. إذا كان اسم المضيف صحيحًا، جرب الاتصال بالخادم عبر سطر الأوامر للتأكد من أنه متاح من نظامك.

    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. إذا كان برنامجك معلقًا في استدعاء طريقة 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
    

هذا كل شيء بالنسبة لمثال JavaMail لإرسال البريد الإلكتروني في جافا باستخدام خادم SMTP مع بروتوكولات مصادقة مختلفة ومرفقات وصور. آمل أن يحل جميع احتياجاتك لإرسال البريد الإلكتروني في برامج جافا.

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