BetterMimeMessage.java
/*
* Copyright (C) 2000 - 2024 Silverpeas
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* As a special exception to the terms and conditions of version 3.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* Open Source Software ("FLOSS") applications as described in Silverpeas's
* FLOSS exception. You should have received a copy of the text describing
* the FLOSS exception, and it is also available here:
* "https://www.silverpeas.org/legal/floss_exception.html"
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package org.silverpeas.components.mailinglist.service.job;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
/**
* @author ehugonnet
*/
public class BetterMimeMessage extends MimeMessage {
public static final String SPAM_FLAG_HEADER = "X-Spam-Flag";
public static final String SPAM_LEVEL_HEADER = "X-Spam-Score";
public static final String AUTO_SUBMITTED_HEADER = "Auto-Submitted";
private final MimeMessage mimeMessage;
public BetterMimeMessage(MimeMessage message) throws MessagingException {
super(message);
this.mimeMessage = message;
}
/**
* Looking for a X-Spam-Flag header in the message.
* @return true if the flag is set to YES, false otherwise.
* @throws MessagingException
*/
public boolean isSpam() throws MessagingException {
String[] spamFlags = this.mimeMessage.getHeader(SPAM_FLAG_HEADER);
if (spamFlags != null) {
for (String flag : spamFlags) {
if ("YES".equalsIgnoreCase(flag)) {
return true;
}
}
}
return false;
}
/**
* Returning the content of the X-Spam-Score header.
* @return the content of the X-Spam-Score header.
* @throws MessagingException
*/
public float getSpamLevel() throws MessagingException {
String[] spamScores = this.mimeMessage.getHeader(SPAM_LEVEL_HEADER);
if (spamScores != null && spamScores.length > 0) {
return Float.parseFloat(spamScores[0]);
}
return 0f;
}
/**
* Indicates if this email is automatic ou bounced .
* @return true if this email is automatic ou bounced - false otherwise.
* @throws IOException
* @throws MessagingException
*/
public boolean isBounced() throws IOException, MessagingException {
if (isAutomaticMessage()) {
return true;
}
if (mimeMessage.getContent() instanceof Multipart) {
Multipart parts = (Multipart) this.mimeMessage.getContent();
for (int i = 0; i < parts.getCount(); i++) {
String contentType = parts.getBodyPart(i).getContentType();
if (isNotification(contentType)) {
return true;
}
}
}
return isNotification(this.mimeMessage.getContentType());
}
protected boolean isAutomaticMessage() throws MessagingException {
String[] autoSubmittedHeaders = this.mimeMessage.getHeader(AUTO_SUBMITTED_HEADER);
if (autoSubmittedHeaders != null) {
for (String autoSubmittedHeader : autoSubmittedHeaders) {
if ("auto-generated".equalsIgnoreCase(autoSubmittedHeader) ||
"auto-replied".equalsIgnoreCase(autoSubmittedHeader) ||
autoSubmittedHeader.startsWith("auto-notified")) {
return true;
}
}
}
return false;
}
protected boolean isNotification(String contentType) {
return isDeliveryStatus(contentType) || isMessageReport(contentType);
}
/**
* Indicates if the corresponding MimeType is a content-type for delivery status notifications
* (DSNs). A DSN can be used to notify the sender of a message of any of several conditions:
* failed delivery, delayed delivery, successful delivery, or the gatewaying of a message into an
* environment that may not support DSNs. The "message/delivery-status" content-type defined
* herein is intended for use within the framework of the "multipart/report" content type
* defined.
* Cf. RFC 1894
* @param contentType the content-type for the mail part.
* @return true if it is a content-type for delivery status.
* @see http://www.ietf.org/rfc/rfc1894.txt
*/
protected boolean isDeliveryStatus(String contentType) {
return "message/delivery-status".equalsIgnoreCase(contentType);
}
/**
* A multipart/report message content, as defined in RFC 3462. A multipart/report content is a
* container for mail reports of any kind, and is most often used to return a delivery status
* report or a disposition notification report.
* @param contentType the content-type for the mail part.
* @return true if it is a content-type for delivery status.
* @see http://www.ietf.org/rfc/rfc3462.txt
*/
protected boolean isMessageReport(String contentType) {
return contentType.startsWith("multipart/report");
}
}