我正尝试从Java邮件(充气城堡1.51)发送S/MIME签名和加密邮件给我自己,以将其发送给我的Outlook。使用Outlook 2010查看S/MIME邮件
我能够发送正常的邮件,但接收是一个问题,因为Outlook不想打开邮件。以下是我尝试打开时出现的错误:
无法打开此项目。您的数字身份证名称不能被底层安全系统找到。
使用p7m查看器可以看到相同的邮件(保存到本地文件的eml格式),表明P12证书已正确安装在我的笔记本电脑上。我在我的Java邮件代码中安装了与我在Keystore中使用的P12文件相同的文件。
我做错了什么? Outlook的问题是否结束?我正在使用Office 365,并希望添加p7m Viewer也无法打开从Outlook WebMail下载的smime.p7m。我收到的错误是:
该文件已损坏;签名信息可能会丢失。
下面是我用来加密/发送邮件的Java代码。
public class BCTest {
public static final String pkcs12Keystore = "C:/Development/Workspace/BouncyCastle_SecureMail/resources/cert/StartCom.p12";
public static final String ksPassword = "ksPassword";
public static final String sendFile = "C:/Development/Workspace/BouncyCastle_SecureMail/resources/hello.txt";
public static final String outputFile = "C:/Development/Workspace/BouncyCastle_SecureMail/output/Encrypted.eml";
public static final String message = "Hi There!!";
public static final String frAddress = "[email protected]";
public static final String toAddress = "[email protected]";
public static final String host = "outlook.office365.com";
public static final int port = 587;
public static final String userName = "[email protected]";
public static final String password = "password";
public static void main(String[] args) {
send();
}
public static void send() {
try {
System.out.println("Setting Mailcap");
MailcapCommandMap mailcap = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mailcap.addMailcap("application/pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_signature");
mailcap.addMailcap("application/pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.pkcs7_mime");
mailcap.addMailcap("application/x-pkcs7-signature;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_signature");
mailcap.addMailcap("application/x-pkcs7-mime;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.x_pkcs7_mime");
mailcap.addMailcap("multipart/signed;; x-java-content-handler=org.bouncycastle.mail.smime.handlers.multipart_signed");
CommandMap.setDefaultCommandMap(mailcap);
/* Add BC */
System.out.println("Setting Bouncy Castle as provider");
Security.addProvider(new BouncyCastleProvider());
/* Open the keystore */
System.out.println("Opening the keystore: " + pkcs12Keystore + " using password " + ksPassword);
KeyStore keystore = KeyStore.getInstance("PKCS12", "BC");
keystore.load(new FileInputStream(pkcs12Keystore), ksPassword.toCharArray());
// Find the first legit alias in the keystore and use it
System.out.println("Getting the keystore alias");
Enumeration<String> e = keystore.aliases();
String keyAlias = null;
while (e.hasMoreElements() && (keyAlias == null)) {
String alias = e.nextElement();
keyAlias = keystore.isKeyEntry(alias) ? alias : null;
}
if (keyAlias == null) {
throw new Exception("Can't find a private key!");
}
Certificate[] chain = keystore.getCertificateChain(keyAlias);
/* Get the private key to sign the message with */
System.out.println("Getting the private key");
PrivateKey privateKey = (PrivateKey) keystore.getKey(keyAlias, ksPassword.toCharArray());
if (privateKey == null) {
throw new Exception("No private key for alias: " + keyAlias);
}
/* Create Email body */
System.out.println("Creating the Email body");
MimeBodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent(message, "text/html");
/* Attach the file to encrypt */
System.out.println("Creating the attachment");
FileDataSource fds = new FileDataSource(sendFile);
MimeBodyPart attachPart = new MimeBodyPart();
attachPart.setDataHandler(new DataHandler(fds));
attachPart.setFileName(fds.getName());
System.out.println("Adding body & attachment to mail");
MimeMultipart bodyMulti = new MimeMultipart();
bodyMulti.addBodyPart(messageBodyPart);
bodyMulti.addBodyPart(attachPart);
System.out.println("Setting mail properties");
Session session = Session.getDefaultInstance(System.getProperties());
MimeMessage body = new MimeMessage(session);
body.setFrom(new InternetAddress(frAddress));
body.setRecipient(Message.RecipientType.TO, new InternetAddress(toAddress));
body.setSentDate(new Date());
body.setSubject("Encrypted Mail");
body.setContent(bodyMulti, bodyMulti.getContentType());
body.saveChanges();
/* Create the SMIMESignedGenerator */
System.out.println("Creating the SMIMESignedGenerator");
SMIMECapabilityVector capabilities = new SMIMECapabilityVector();
capabilities.addCapability(SMIMECapability.dES_EDE3_CBC);
capabilities.addCapability(SMIMECapability.rC2_CBC, 128);
capabilities.addCapability(SMIMECapability.dES_CBC);
capabilities.addCapability(SMIMECapability.aES256_CBC);
System.out.println("Creating the ASN1EncodableVector");
ASN1EncodableVector attributes = new ASN1EncodableVector();
attributes.add(new SMIMEEncryptionKeyPreferenceAttribute(new IssuerAndSerialNumber(new X500Name(((X509Certificate) chain[0])
.getIssuerDN().getName()), ((X509Certificate) chain[0]).getSerialNumber())));
attributes.add(new SMIMECapabilitiesAttribute(capabilities));
System.out.println("Adding certificate");
List<X509Certificate> certList = new ArrayList<X509Certificate>();
certList.add((X509Certificate) chain[0]);
SMIMESignedGenerator gen = new SMIMESignedGenerator("binary");
gen.addSignerInfoGenerator(new JcaSimpleSignerInfoGeneratorBuilder().setProvider("BC").build("SHA1withRSA", privateKey,
(X509Certificate) chain[0]));
gen.addCertificates(new JcaCertStore(certList));
MimeMultipart multiPart = gen.generate(body);
MimeMessage signedMessage = new MimeMessage(session);
System.out.println("Creating Mime Message");
@SuppressWarnings("unchecked")
Enumeration<String> headers = body.getAllHeaderLines();
while (headers.hasMoreElements()) {
signedMessage.addHeaderLine(headers.nextElement());
}
signedMessage.setContent(multiPart);
signedMessage.saveChanges();
/* Create the encrypter and encrypt the message */
System.out.println("Encrypting Mime Message");
SMIMEEnvelopedGenerator fact = new SMIMEEnvelopedGenerator();
fact.addRecipientInfoGenerator(new JceKeyTransRecipientInfoGenerator((X509Certificate) chain[0]).setProvider("BC"));
MimeBodyPart encryptedPart = fact.generate(signedMessage, new JceCMSContentEncryptorBuilder(CMSAlgorithm.RC2_CBC, 40)
.setProvider("BC").build());
encryptedPart.setHeader("Content-Transfer-Encoding", "binary");
ByteArrayOutputStream out = new ByteArrayOutputStream();
encryptedPart.writeTo(out);
/* Create a new MimeMessage for the encrypted and signed content */
System.out.println("Setting mail server properties");
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Session smtpSession = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
});
MimeMessage smtpMessage = new MimeMessage(smtpSession, new ByteArrayInputStream(out.toByteArray()));
smtpMessage.saveChanges();
/* Set all original MIME headers in the encrypted message */
@SuppressWarnings("unchecked")
Enumeration<String> orgHeaders = body.getAllHeaderLines();
while (orgHeaders.hasMoreElements()) {
String headerLine = (String) orgHeaders.nextElement();
/* Do not override content-* headers from the original message */
if (!Strings.toLowerCase(headerLine).startsWith("content-")) {
smtpMessage.addHeaderLine(headerLine);
}
}
System.out.println("Creating eml file as location: " + outputFile);
smtpMessage.writeTo(new FileOutputStream(outputFile));
System.out.println("Sending Mail");
Transport.send(smtpMessage);
System.out.println("Mail Sent");
} catch (SMIMEException ex) {
ex.getUnderlyingException().printStackTrace(System.err);
ex.printStackTrace(System.err);
} catch (Exception ex) {
ex.printStackTrace(System.err);
}
}
}
PLZ帮助!
问候
另外,您也可以直接双击.p12文件开始导入过程 – Jeff 2014-11-13 18:09:49
感谢杰夫。是的,试过但没有工作!我收到了同样的错误。 – Sumit 2014-11-17 07:47:49
我在Outlook中遇到了一个问题,在其中一个电子邮件标题中出现了无意中的换行符。删除换行突然让Outlook开心,我可以再次查看消息。其他客户更容忍畸形标题。难道你的电子邮件在某个地方有一个不好的标题? – Jeff 2014-12-02 16:53:43