Skip to content

Commit 1cb7960

Browse files
committed
Merge branch 'smtp-message-support'
2 parents d626543 + 0137f24 commit 1cb7960

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
.project
66
.classpath
77
.checkstyle
8+
/.idea
9+
/*.iml

src/main/java/net/markenwerk/utils/mail/smime/SmimeUtil.java

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,18 @@
5353
import javax.mail.internet.MimeMultipart;
5454
import javax.mail.internet.MimePart;
5555

56+
import com.sun.mail.smtp.SMTPMessage;
5657
import org.bouncycastle.asn1.ASN1EncodableVector;
5758
import org.bouncycastle.asn1.cms.AttributeTable;
5859
import org.bouncycastle.asn1.cms.IssuerAndSerialNumber;
5960
import org.bouncycastle.asn1.smime.SMIMECapabilitiesAttribute;
6061
import org.bouncycastle.asn1.smime.SMIMECapability;
6162
import org.bouncycastle.asn1.smime.SMIMECapabilityVector;
6263
import org.bouncycastle.asn1.smime.SMIMEEncryptionKeyPreferenceAttribute;
64+
import org.bouncycastle.asn1.x500.RDN;
6365
import org.bouncycastle.asn1.x500.X500Name;
66+
import org.bouncycastle.asn1.x500.style.BCStyle;
67+
import org.bouncycastle.asn1.x500.style.IETFUtils;
6468
import org.bouncycastle.cert.X509CertificateHolder;
6569
import org.bouncycastle.cert.jcajce.JcaCertStore;
6670
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
@@ -390,23 +394,28 @@ private static JcaCertStore getCertificateStore(SmimeKey smimeKey) throws Certif
390394
}
391395
return new JcaCertStore(certificateList);
392396
}
393-
397+
394398
/**
395399
* Signs a MIME message and yields a new S/MIME signed MIME message.
396-
*
400+
*
397401
* @param session
398402
* The {@link Session} that is used in conjunction with the
399403
* original {@link MimeMessage}.
400404
* @param mimeMessage
401-
* The original {@link MimeMessage} to be signed.
405+
* The original {@link MimeMessage} or {@link SMTPMessage} to be signed.
402406
* @param smimeKey
403407
* The {@link SmimeKey} used to obtain the {@link PrivateKey} to
404408
* sign the original message with.
405-
* @return The new S/MIME signed {@link MimeMessage}.
409+
* @return The new S/MIME signed {@link MimeMessage} or {@link SMTPMessage}.
406410
*/
407-
public static MimeMessage sign(Session session, MimeMessage mimeMessage, SmimeKey smimeKey) {
411+
public static <T extends MimeMessage> T sign(Session session, T mimeMessage, SmimeKey smimeKey) {
412+
return (mimeMessage instanceof SMTPMessage)
413+
? sign(mimeMessage, (T) new SMTPMessage(session), smimeKey)
414+
: sign(mimeMessage, (T) new MimeMessage(session), smimeKey);
415+
}
416+
417+
private static <T extends MimeMessage> T sign(T mimeMessage, T signedMessage, SmimeKey smimeKey) {
408418
try {
409-
MimeMessage signedMessage = new MimeMessage(session);
410419
copyHeaderLines(mimeMessage, signedMessage);
411420
copyContent(sign(extractMimeBodyPart(mimeMessage), smimeKey), signedMessage);
412421
return signedMessage;
@@ -491,6 +500,61 @@ private static boolean checkSignature(SMIMESigned smimeSigned) throws MessagingE
491500
throw handledException(e);
492501
}
493502
}
503+
504+
/**
505+
* @param mimeMultipart
506+
* The {@link MimeMultipart} to be checked.
507+
* @return The subject / address to which the certificate was issued to. Email clients may use this to show
508+
* {@code "Signed by: <subject / address>"}
509+
*/
510+
public static String getSignedByAddress(MimeMultipart mimeMultipart) {
511+
try {
512+
return getSignedByAddress(new SMIMESigned(mimeMultipart));
513+
} catch (Exception e) {
514+
throw handledException(e);
515+
}
516+
}
517+
518+
/**
519+
* @param mimePart
520+
* The {@link MimePart} to be checked.
521+
* @return The subject / address to which the certificate was issued to. Email clients may use this to show
522+
* {@code "Signed by: <subject / address>"}
523+
*/
524+
public static String getSignedByAddress(MimePart mimePart) {
525+
try {
526+
if (mimePart.isMimeType("multipart/signed")) {
527+
return getSignedByAddress(new SMIMESigned((MimeMultipart) mimePart.getContent()));
528+
} else if (mimePart.isMimeType("application/pkcs7-mime") || mimePart.isMimeType("application/x-pkcs7-mime")) {
529+
return getSignedByAddress(new SMIMESigned(mimePart));
530+
} else {
531+
throw new SmimeException("Message not signed");
532+
}
533+
} catch (Exception e) {
534+
throw handledException(e);
535+
}
536+
}
537+
538+
/**
539+
* Returns the subject / address to which the certificate was issued to. Email clients may use this to show
540+
* {@code "Signed by: <subject / address>"}
541+
*/
542+
private static String getSignedByAddress(SMIMESigned smimeSigned) {
543+
try {
544+
@SuppressWarnings("rawtypes")
545+
Store certificates = smimeSigned.getCertificates();
546+
547+
SignerInformation signerInformation = smimeSigned.getSignerInfos().getSigners().iterator().next();
548+
X509Certificate certificate = getCertificate(certificates, signerInformation.getSID());
549+
SignerInformationVerifier verifier = getVerifier(certificate);
550+
X500Name x500name = verifier.getAssociatedCertificate().getSubject();
551+
RDN cn = x500name.getRDNs(BCStyle.CN)[0];
552+
return IETFUtils.valueToString(cn.getFirst().getValue());
553+
554+
} catch (Exception e) {
555+
throw handledException(e);
556+
}
557+
}
494558

495559
private static X509Certificate getCertificate(@SuppressWarnings("rawtypes") Store certificates, SignerId signerId)
496560
throws CertificateException {

0 commit comments

Comments
 (0)