使用 p7s 数字签名的 Android Intent 来签署电子邮件

标签 android email android-intent digital-signature email-attachments

我正在尝试发送一个由用户选择的电子邮件应用处理的 Intent。 Intent 有一个签名作为附件。我了解到 Gmail 应用程序无法处理自定义 MIME 类型,因此我点击 K-9 邮件来处理 Intent 。

Intent emailIntent = new Intent(Intent.ACTION_SEND);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"foo@bar.com"});
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email test");
emailIntent.putExtra(Intent.EXTRA_TEXT, confirmEmailBody);
emailIntent.putExtra(Intent.EXTRA_STREAM, uriSigned);
emailIntent.setType("application/pkcs7-signature");
try {
    startActivity(Intent.createChooser(emailIntent, "Sending email..."));
} catch (android.content.ActivityNotFoundException ex) {
    Toast.makeText(this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}

我有一个 p7s 文件(存在于 SD 卡上)的 uriSigned,它是从字符串 confirmEmailBody 生成的。上面的 Intent 设置附件属性如下:

Content-Transfer-Encoding: base64
Content-Type: application/pkcs7-signature;
 name="smime.p7s"
Content-Disposition: attachment;
 filename="smime.p7s";
 size=1886

但是,附件未被发现为签名,因为一般电子邮件内容类型(位于发件人信息、时间等旁边)是多部分/混合的,而它应该是多部分/已签名的。 如何在 Intent 中设置 header ,使其在电子邮件中最终显示为 Content-Type: multipart/signed;

在它显示为签名后,我将查看它是否会根据电子邮件正文进行验证。

附言当然,我可以使用 javamail 轻松发送正确签名的电子邮件,但我想避免询问用户手机的 gmail 密码。

最佳答案

由于我没能找到让这项工作按我想要的方式进行的方法,我想我会发布我的替代方法来解决这个问题,但仍然避免询问密码。我使用 Google Play 服务获取 Auth2 token 。

String token = GoogleAuthUtil.getToken(context, userEmail, "oauth2:https://mail.google.com/");
SMTPTransport smtpTransport = connectToSmtp("smtp.gmail.com", 587, userEmail, token, true);

SMTPMessage smtpMessage = new SMTPMessage(smtpSession);
smtpMessage.setFrom(new InternetAddress(userEmail));
smtpMessage.addRecipient(Message.RecipientType.TO, toAddress);
smtpMessage.setSubject(subject);
smtpMessage.setContent(multipart, multipart.getContentType());
smtpMessage.saveChanges();

smtpTransport.sendMessage(smtpMessage, smtpMessage.getAllRecipients());
smtpTransport.close();

当然,您可以选择适合您需要的 oauth2 范围。要设置 SMTPTransport 以接受 token (并为上面的代码创建 smtpSession):

private SMTPTransport connectToSmtp(String host, int port, String userEmail, String oauthToken, boolean debug) throws Exception {
        Properties props = new Properties();
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.smtp.starttls.required", "true");
        props.put("mail.smtp.sasl.enable", "true");
        props.put("mail.smtp.sasl.mechanisms", "XOAUTH2");
        props.put("mail.imaps.sasl.mechanisms.oauth2.oauthToken", oauthToken);
        smtpSession = Session.getInstance(props);
        smtpSession.setDebug(debug);

        final URLName unusedUrlName = null;
        SMTPTransport transport = new SMTPTransport(smtpSession, unusedUrlName);
        // If the password is non-null, SMTP tries to do AUTH LOGIN.
        final String emptyPassword = null;
        transport.connect(host, port, userEmail, emptyPassword);

        byte[] responseTemp = String.format("user=%s\1auth=Bearer %s\1\1", userEmail, oauthToken).getBytes();
        byte[] response = BASE64EncoderStream.encode(responseTemp);
        transport.issueCommand("AUTH XOAUTH2 " + new String(response), 235);

        return transport;
}

有关详细信息,请参阅以下链接:Authorizing with Google on Android , OAuth2 info

关于使用 p7s 数字签名的 Android Intent 来签署电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24824501/

相关文章:

android - 一个 OnClickHandler 用于多个按钮

java - PhoneGap : Inject JS into HTML on page load through Java on Android

email - 向消息正文添加额外的字符串(swift)

javascript - 钛金android,接收intent,如何访问原生文件?

Android IMAGE_CAPTURE Intent 在 onActivityResult 之后保存照片

android - 不推荐使用的单词是fill_parent和match_parent之间的唯一区别

android - 华为云数据库创建对象类型()崩溃

php - 如何通过电子邮件发送数据库中的一长串电子邮件?

html - 强制 Gmail for iPhone 以指定的宽度呈现表格单元格?

android - 单击 Android 通知操作不会关闭通知抽屉