在 JAVA 中通过 gmail smtp 服务器发送电子邮件

Posted

技术标签:

【中文标题】在 JAVA 中通过 gmail smtp 服务器发送电子邮件【英文标题】:Sending Email via gmail smtp server in JAVA 【发布时间】:2013-03-13 22:04:09 【问题描述】:

这段代码有什么问题?不知何故,它进入了Transport.send(message); 行的无限循环,没有错误消息,没有异常,只是可能无限循环(我不知道,因为我等待的时间不超过 5-10 分钟)

final String username = "<mail_name>";
final String password = "<password>";

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "465");

Session session = Session.getInstance(props,
        new javax.mail.Authenticator() 
            protected PasswordAuthentication getPasswordAuthentication() 
                return new PasswordAuthentication(username, password);
            
        );

try 

    Message message = new MimeMessage(session);
    message.setFrom(new InternetAddress("<mail_from>@gmail.com"));
    message.setRecipients(Message.RecipientType.TO,
            InternetAddress.parse("<mail_to>@gmail.com"));
    message.setSubject("Test Subject");
    message.setText("Test");

    Transport.send(message);

    System.out.println("Done");

 catch (MessagingException e) 
    throw new RuntimeException(e);

【问题讨论】:

我建议在MessagingException 之后添加一个catch (Exception e),以查看是否会引发其他类型的异常。还要添加一个finally 块。您还可以添加log4j.xml 并将javax.mail 类设置为DEBUG,看看还会发生什么。 很好的提示,谢谢!会测试它 不幸的是仍在 Transport.send(message) 线上等待...有人可以验证此代码的正确性吗? 【参考方案1】:

使用Simple Java Mail 应该很简单:

Email email = new Email();

email.setFromAddress("lollypop", "lol.pop@somemail.com");
email.addRecipient("C.Cane", "candycane@candyshop.org", RecipientType.TO);
email.setText("We should meet up!");
email.setTexthtml("<b>We should meet up!</b>");
email.setSubject("hey");

new Mailer("smtp.gmail.com", 25, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email);
new Mailer("smtp.gmail.com", 587, "your user", "your password", TransportStrategy.SMTP_TLS).sendMail(email);
new Mailer("smtp.gmail.com", 465, "your user", "your password", TransportStrategy.SMTP_SSL).sendMail(email);

如果您启用了双因素登录,则需要从您的 Google 帐户生成application specific password。

【讨论】:

【参考方案2】:

好的。它比我第一次提出的要复杂一些......总结一下我得到了什么:

有一个非常有用的命令:session.setDebug(true);。如果你设置为真,每一个重要的进程都会被调试到控制台。我建议使用它。 第二台计算机只能使用安全选项,您可以切换这台计算机:Transport transport = session.getTransport("smtps"); 而不是非安全 smtp... JavaMail API 传输对象也将处理端口(分别为 smtp: 587 , smtps: 465)

你也可以使用Transport类的静态方法发送消息和(之前保存,非静态sendMessage方法不会保存消息),但是这次你需要使用javax.mail.Authenticator会话创建,如下所示:

Session session = Session.getInstance(props,         new javax.mail.Authenticator() 
    protected PasswordAuthentication getPasswordAuthentication() 
        return new PasswordAuthentication("login", "password");
    

);

1.4.2 JavaMailApi 对于这个问题除了 1.4.7 版本还有另一个异常...

如果不使用,则无法使用静态方法进行身份验证。如果你使用实例方法,你可以。

一台计算机有 maven 并获得了 1.4.2 版本的 JavaMail API。第二台电脑有一个下载的库,版本为 1.4.7,我想这也弄乱了东西 第一个comp Netbeans,第二个comp Intellij... +1) 互联网上有很多陈旧且糟糕的示例代码,这使得正确使用此 API 变得更加困难。

太乱了,但有一些基本概念应该重点关注...

【讨论】:

【参考方案3】:

我在这里进行了一些更改,这对我来说很好用:

Session session = Session.getInstance(props,null);

你像你一样实例化消息对象。最后:

Transport transport = session.getTransport("smtp");
String mfrom = "yourGmailUsernameWithout@"// example laabidiraissi 
transport.connect("smtp.gmail.com", mfrom, "thepassword");
transport.sendMessage(message, message.getAllRecipients());

编辑,请您帮我一个忙,复制/粘贴并尝试这个示例并显示它显示的内容:

package com.test;

import java.util.Properties;

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.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.junit.Test;

public class EmailService 

@Test
public void test()
    Properties props = System.getProperties();
    props.put("mail.smtp.starttls.enable", true); // added this line
    props.put("mail.smtp.host", "smtp.gmail.com");
    props.put("mail.smtp.user", "username");
    props.put("mail.smtp.password", "password");
    props.put("mail.smtp.port", "587");
    props.put("mail.smtp.auth", true);



    Session session = Session.getInstance(props,null);
    MimeMessage message = new MimeMessage(session);

    System.out.println("Port: "+session.getProperty("mail.smtp.port"));

    // Create the email addresses involved
    try 
        InternetAddress from = new InternetAddress("username");
        message.setSubject("Yes we can");
        message.setFrom(from);
        message.addRecipients(Message.RecipientType.TO, InternetAddress.parse("receivermail"));

        // Create a multi-part to combine the parts
        Multipart multipart = new MimeMultipart("alternative");

        // Create your text message part
        BodyPart messageBodyPart = new MimeBodyPart();
        messageBodyPart.setText("some text to send");

        // Add the text part to the multipart
        multipart.addBodyPart(messageBodyPart);

        // Create the html part
        messageBodyPart = new MimeBodyPart();
        String htmlMessage = "Our html text";
        messageBodyPart.setContent(htmlMessage, "text/html");


        // Add html part to multi part
        multipart.addBodyPart(messageBodyPart);

        // Associate multi-part with message
        message.setContent(multipart);

        // Send message
        Transport transport = session.getTransport("smtp");
        transport.connect("smtp.gmail.com", "username", "password");
        System.out.println("Transport: "+transport.toString());
        transport.sendMessage(message, message.getAllRecipients());


     catch (AddressException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
     catch (MessagingException e) 
        // TODO Auto-generated catch block
        e.printStackTrace();
    


【讨论】:

谢谢,但 mail.smtp.auth 属性已经存在...而且我也尝试过使用其他端口。 对不起 auth 属性,这是我的错,我没看到。 如果尝试使用 25 或 587 端口,无论如何检查您的解决方案...线程“main”中的异常 java.lang.RuntimeException:javax.mail.MessagingException:无法连接到 SMTP 主机: smtp.gmail.com,端口:25;嵌套异常是:java.net.ConnectException:连接被拒绝:连接 还是一样的异常,会不会是我的网络配置不对? 终于有好消息了,我们有一些例外。你的例外是经典的:***.com/questions/7158951/…【参考方案4】:

我可以重现您问题中描述的行为并修复它。

send 方法卡在

SMTPTransport(Service).connect(String, int, String, String) line: 308   

连接不成功,因为您的 gmail smtp 主机端口错误:465

改成587

props.put("mail.smtp.port", "587");

它会起作用的。

【讨论】:

是的,不知道我为什么要骑465端口,但无论如何,它仍然无法正常工作:( 您现在遇到什么异常/错误?您的 java.exe 是否允许通过防火墙? This:java.lang.RuntimeException: javax.mail.MessagingException: 无法连接到 SMTP 主机:smtp.gmail.com,端口:25;嵌套异常是:java.net.ConnectException:连接被拒绝:连接我关闭了整个 Windows 防火墙.. 您的应用似乎不支持 SSL。 smtp.gmail.com 需要安全连接,否则您将不得不选择另一个主机 see google support page。您可能需要通过获取支持安全协议smtpsTransport 实例来明确指定它,并使用它来发送您的消息。请参考accepted answer for this question

以上是关于在 JAVA 中通过 gmail smtp 服务器发送电子邮件的主要内容,如果未能解决你的问题,请参考以下文章

如何在 php 中通过 gmail 使用 mail()

使用 Gmail 在 codeigniter 中通过电子邮件类发送电子邮件

在 Visual Studio 中通过 C# (Selenium) 自动登录 Gmail

EmailBackend 用于在 Django 中通过多个 SMTP 发送电子邮件

使用 C# 通过 Gmail SMTP 服务器发送电子邮件

为啥编码标头内容类型:text/html;在 Outlook 插件中使用 MailItem 时缺少 GMAIL 的 SMTP 服务器:SMTP.GMAIL.COM?