使用Apache Commons Net SMTP以Java(和Android)发送邮件:STARTTLS,SSL

最近我正在做一个Android实验,我想使用SMTP服务器通过android应用程序通过身份验证和加密来发送电子邮件。

好吧, 我发现Android上的javax.mail并不是一个很好的选择 ,因为它取决于awt类(我猜是传统); 有些人试图对其进行调整,以使您不需要整个awt软件包 ,但我在此方面收效甚微。 更不用说那些人几年前自己重构了Android的javax.mail,没有任何维护。

我想到的另一个选择是重新使用Apache Commons Net由于该社区向原始SMTP客户端添加了SMTPSClient和AuthenticatingSMTPClient并为SSL和身份验证应用了我的一点补丁 ),因此您可以将该库嵌入Android应用程序(无需传递依赖项)以在安全层上使用身份验证发送邮件。 ( 这篇文章实际上激发了我的灵感 ,但是它使用的是Apache Commons Net的旧版本,而使用3.3则不再需要这样做)

SMTP身份验证和具有Commons Net的STARTTLS

通常,用于此问题的端口是25或备用587端口:您通过普通连接连接到SMTP服务器,要求提供可用的命令,如果支持STARTTLS,则使用它,其余的通信将被加密。

让我们以gmail为例,因为smtp.gmail.com支持身份验证和STARTTLS

public void sendEmail() throws Exception {  
    String hostname = "smtp.gmail.com";
    int port = 587;
 
    String password = "gmailpassword";
    String login = "account@gmail.com";
 
    String from = login;
 
    String subject = "subject" ;
    String text = "message";
 
    AuthenticatingSMTPClient client = new AuthenticatingSMTPClient();
    try {
      String to = "recipient@email.com";
      // optionally set a timeout to have a faster feedback on errors
      client.setDefaultTimeout(10 * 1000);
      // you connect to the SMTP server
      client.connect(hostname, port);
      // you say ehlo  and you specify the host you are connecting from, could be anything
      client.ehlo("localhost");
      // if your host accepts STARTTLS, we're good everything will be encrypted, otherwise we're done here
      if (client.execTLS()) {
 
        client.auth(AuthenticatingSMTPClient.AUTH_METHOD.LOGIN, login, password);
        checkReply(client);
 
        client.setSender(from);
        checkReply(client);
 
        client.addRecipient(to);
        checkReply(client);
 
        Writer writer = client.sendMessageData();
 
        if (writer != null) {
          SimpleSMTPHeader header = new SimpleSMTPHeader(from, to, subject);
          writer.write(header.toString());
          writer.write(text);
          writer.close();
          if(!client.completePendingCommand()) {// failure
            throw new Exception("Failure to send the email "+ client.getReply() + client.getReplyString());
          }
        } else {
          throw new Exception("Failure to send the email "+ client.getReply() + client.getReplyString());
        }
      } else {
        throw new Exception("STARTTLS was not accepted "+ client.getReply() + client.getReplyString());
      }
    } catch (Exception e) {
        throw e;
    } finally {
        client.logout();
        client.disconnect();
    }
  }
 
  private static void checkReply(SMTPClient sc) throws Exception {
    if (SMTPReply.isNegativeTransient(sc.getReplyCode())) {
      throw new Exception("Transient SMTP error " + sc.getReply() + sc.getReplyString());
    } else if (SMTPReply.isNegativePermanent(sc.getReplyCode())) {
      throw new Exception("Permanent SMTP error " + sc.getReply() + sc.getReplyString());
    }

这里没有什么可添加的,当然,如果您使用自己的异常类,则可以优化异常处理。

带有Commons Net的SMTP身份验证和SSL

某些SMTP服务器配置为仅接受“ a到z SSL”:您必须在向服务器发出任何命令之前确保通信的安全; 通常使用的端口是465。

让我们以LaPoste.net示例(法语帖子提供的免费电子邮件帐户)为例:

public void sendEmail() throws Exception {  
    String hostname = "smtp.laposte.net";
    int port = 465;
 
    String password = "password";
    String login = "firstname.lastname";
 
    String from = login + "@laposte.net";
 
    String subject = "subject" ;
    String text = "message";
 
    // this is the important part : you tell your client to connect using SSL right away
    AuthenticatingSMTPClient client = new AuthenticatingSMTPClient("TLS",true);
    try {
      String to = "anthony.dahanne@gmail.com";
      // optionally set a timeout to have a faster feedback on errors
      client.setDefaultTimeout(10 * 1000);
      client.connect(hostname, port);
      client.ehlo("localhost");
      client.auth(AuthenticatingSMTPClient.AUTH_METHOD.LOGIN, login, password);
      checkReply(client);
 
      client.setSender(from);
      checkReply(client);
 
      client.addRecipient(to);
      checkReply(client);
 
      Writer writer = client.sendMessageData();
 
      if (writer != null) {
        SimpleSMTPHeader header = new SimpleSMTPHeader(from, to, subject);
        writer.write(header.toString());
        writer.write(text);
        writer.close();
        if(!client.completePendingCommand()) {// failure
          throw new Exception("Failure to send the email "+ client.getReply() + client.getReplyString());
        }
      } else {
        throw new Exception("Failure to send the email "+ client.getReply() + client.getReplyString());
      }
    } catch (Exception e) {
        throw e;
    } finally {
        client.logout();
        client.disconnect();
    }

我在这里没有重复checkReply()方法,因为两个代码段都相同。 您会注意到,立即使用SSL意味着您不必检查execTls()响应(实际上,如果这样做,它将无法正常工作)。

包起来

就是这样 如果要使这些示例在您的环境中工作,则可以将apache commons net 3.3 jar添加到您的类路径中

如果您使用的是Maven,请添加依赖项:

<dependency>
    <groupid>commons-net</groupid>
    <artifactid>commons-net</artifactid>
    <version>3.3</version>
</dependency>

如果您将Gradle用于Android项目,则还可以使用以下build.gradle文件:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.4.2'
    }
}
apply plugin: 'android'
 
repositories {
    mavenCentral()
}
 
dependencies {
    compile fileTree(dir: 'libs', include: '*.jar'), 'commons-net:commons-net:3.3'
}
 
android {
    compileSdkVersion 17
    buildToolsVersion "17.0.0"
 
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
 
        instrumentTest.setRoot('tests')
    }
}

请享用 !


翻译自: https://www.javacodegeeks.com/2013/11/sending-a-mail-in-java-and-android-with-apache-commons-net-smtp-starttls-ssl.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值