我正在尝试发送一个由用户选择的电子邮件应用处理的 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/