精简邮件通知组件
This commit is contained in:
parent
3600c0980e
commit
e0162e100e
@ -23,12 +23,6 @@
|
|||||||
<artifactId>notify-core</artifactId>
|
<artifactId>notify-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-context-support</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>fastjson</artifactId>
|
<artifactId>fastjson</artifactId>
|
||||||
|
@ -5,6 +5,9 @@ import com.simaek.notify.*;
|
|||||||
import com.simaek.notify.email.EmailProvider;
|
import com.simaek.notify.email.EmailProvider;
|
||||||
import com.simaek.notify.email.EmailTemplate;
|
import com.simaek.notify.email.EmailTemplate;
|
||||||
import com.simaek.notify.email.EmailTemplateParsed;
|
import com.simaek.notify.email.EmailTemplateParsed;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.JavaMailSender;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.JavaMailSenderImpl;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.MimeMessageHelper;
|
||||||
import com.simaek.notify.util.ExpressionUtils;
|
import com.simaek.notify.util.ExpressionUtils;
|
||||||
import com.simaek.notify.util.StringUtils;
|
import com.simaek.notify.util.StringUtils;
|
||||||
import okhttp3.Call;
|
import okhttp3.Call;
|
||||||
@ -16,9 +19,6 @@ import org.jsoup.nodes.Document;
|
|||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.core.io.InputStreamSource;
|
import org.springframework.core.io.InputStreamSource;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
|
||||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
|
||||||
|
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown on failed authentication.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
|
public class MailAuthenticationException extends MailException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailAuthenticationException.
|
||||||
|
*
|
||||||
|
* @param msg message
|
||||||
|
*/
|
||||||
|
public MailAuthenticationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailAuthenticationException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailAuthenticationException(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailAuthenticationException.
|
||||||
|
*
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailAuthenticationException(Throwable cause) {
|
||||||
|
super("Authentication failed", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import org.springframework.core.NestedRuntimeException;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all mail exceptions.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
*/
|
||||||
|
public abstract class MailException extends NestedRuntimeException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
*/
|
||||||
|
public MailException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailException(@Nullable String msg, @Nullable Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.MimeMessageHelper;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a common interface for mail messages, allowing a user to set key
|
||||||
|
* values required in assembling a mail message, without needing to know if
|
||||||
|
* the underlying message is a simple text message or a more sophisticated
|
||||||
|
* MIME message.
|
||||||
|
*
|
||||||
|
* <p>Implemented by both SimpleMailMessage and MimeMessageHelper,
|
||||||
|
* to let message population code interact with a simple message or a
|
||||||
|
* MIME message through a common interface.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see SimpleMailMessage
|
||||||
|
* @see MimeMessageHelper
|
||||||
|
* @since 1.1.5
|
||||||
|
*/
|
||||||
|
public interface MailMessage {
|
||||||
|
|
||||||
|
void setFrom(String from) throws MailParseException;
|
||||||
|
|
||||||
|
void setReplyTo(String replyTo) throws MailParseException;
|
||||||
|
|
||||||
|
void setTo(String to) throws MailParseException;
|
||||||
|
|
||||||
|
void setTo(String... to) throws MailParseException;
|
||||||
|
|
||||||
|
void setCc(String cc) throws MailParseException;
|
||||||
|
|
||||||
|
void setCc(String... cc) throws MailParseException;
|
||||||
|
|
||||||
|
void setBcc(String bcc) throws MailParseException;
|
||||||
|
|
||||||
|
void setBcc(String... bcc) throws MailParseException;
|
||||||
|
|
||||||
|
void setSentDate(Date sentDate) throws MailParseException;
|
||||||
|
|
||||||
|
void setSubject(String subject) throws MailParseException;
|
||||||
|
|
||||||
|
void setText(String text) throws MailParseException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown if illegal message properties are encountered.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
|
public class MailParseException extends MailException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailParseException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
*/
|
||||||
|
public MailParseException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailParseException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailParseException(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailParseException.
|
||||||
|
*
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailParseException(Throwable cause) {
|
||||||
|
super("Could not parse mail", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception to be thrown by user code if a mail cannot be prepared properly,
|
||||||
|
* for example when a FreeMarker template cannot be rendered for the mail text.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 1.1
|
||||||
|
*/
|
||||||
|
public class MailPreparationException extends MailException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailPreparationException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
*/
|
||||||
|
public MailPreparationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailPreparationException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailPreparationException(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MailPreparationException(Throwable cause) {
|
||||||
|
super("Could not prepare mail", cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,184 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a mail sending error is encountered.
|
||||||
|
* Can register failed messages with their exceptions.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
|
public class MailSendException extends MailException {
|
||||||
|
|
||||||
|
private final transient Map<Object, Exception> failedMessages;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final Exception[] messageExceptions;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailSendException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
*/
|
||||||
|
public MailSendException(String msg) {
|
||||||
|
this(msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for MailSendException.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
*/
|
||||||
|
public MailSendException(String msg, @Nullable Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
this.failedMessages = new LinkedHashMap<>();
|
||||||
|
this.messageExceptions = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for registration of failed messages, with the
|
||||||
|
* messages that failed as keys, and the thrown exceptions as values.
|
||||||
|
* <p>The messages should be the same that were originally passed
|
||||||
|
* to the invoked send method.
|
||||||
|
*
|
||||||
|
* @param msg the detail message
|
||||||
|
* @param cause the root cause from the mail API in use
|
||||||
|
* @param failedMessages a Map of failed messages as keys and thrown
|
||||||
|
* exceptions as values
|
||||||
|
*/
|
||||||
|
public MailSendException(@Nullable String msg, @Nullable Throwable cause, Map<Object, Exception> failedMessages) {
|
||||||
|
super(msg, cause);
|
||||||
|
this.failedMessages = new LinkedHashMap<>(failedMessages);
|
||||||
|
this.messageExceptions = failedMessages.values().toArray(new Exception[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for registration of failed messages, with the
|
||||||
|
* messages that failed as keys, and the thrown exceptions as values.
|
||||||
|
* <p>The messages should be the same that were originally passed
|
||||||
|
* to the invoked send method.
|
||||||
|
*
|
||||||
|
* @param failedMessages a Map of failed messages as keys and thrown
|
||||||
|
* exceptions as values
|
||||||
|
*/
|
||||||
|
public MailSendException(Map<Object, Exception> failedMessages) {
|
||||||
|
this(null, null, failedMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a Map with the failed messages as keys, and the thrown exceptions
|
||||||
|
* as values.
|
||||||
|
* <p>Note that a general mail server connection failure will not result
|
||||||
|
* in failed messages being returned here: A message will only be
|
||||||
|
* contained here if actually sending it was attempted but failed.
|
||||||
|
* <p>The messages will be the same that were originally passed to the
|
||||||
|
* invoked send method, that is, SimpleMailMessages in case of using
|
||||||
|
* the generic MailSender interface.
|
||||||
|
* <p>In case of sending MimeMessage instances via JavaMailSender,
|
||||||
|
* the messages will be of type MimeMessage.
|
||||||
|
* <p><b>NOTE:</b> This Map will not be available after serialization.
|
||||||
|
* Use {@link #getMessageExceptions()} in such a scenario, which will
|
||||||
|
* be available after serialization as well.
|
||||||
|
*
|
||||||
|
* @return the Map of failed messages as keys and thrown exceptions as values
|
||||||
|
* @see SimpleMailMessage
|
||||||
|
* @see javax.mail.internet.MimeMessage
|
||||||
|
*/
|
||||||
|
public final Map<Object, Exception> getFailedMessages() {
|
||||||
|
return this.failedMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an array with thrown message exceptions.
|
||||||
|
* <p>Note that a general mail server connection failure will not result
|
||||||
|
* in failed messages being returned here: A message will only be
|
||||||
|
* contained here if actually sending it was attempted but failed.
|
||||||
|
*
|
||||||
|
* @return the array of thrown message exceptions,
|
||||||
|
* or an empty array if no failed messages
|
||||||
|
*/
|
||||||
|
public final Exception[] getMessageExceptions() {
|
||||||
|
return (this.messageExceptions != null ? this.messageExceptions : new Exception[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String getMessage() {
|
||||||
|
if (ObjectUtils.isEmpty(this.messageExceptions)) {
|
||||||
|
return super.getMessage();
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String baseMessage = super.getMessage();
|
||||||
|
if (baseMessage != null) {
|
||||||
|
sb.append(baseMessage).append(". ");
|
||||||
|
}
|
||||||
|
sb.append("Failed messages: ");
|
||||||
|
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||||
|
Exception subEx = this.messageExceptions[i];
|
||||||
|
sb.append(subEx.toString());
|
||||||
|
if (i < this.messageExceptions.length - 1) {
|
||||||
|
sb.append("; ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (ObjectUtils.isEmpty(this.messageExceptions)) {
|
||||||
|
return super.toString();
|
||||||
|
} else {
|
||||||
|
StringBuilder sb = new StringBuilder(super.toString());
|
||||||
|
sb.append("; message exceptions (").append(this.messageExceptions.length).append(") are:");
|
||||||
|
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||||
|
Exception subEx = this.messageExceptions[i];
|
||||||
|
sb.append('\n').append("Failed message ").append(i + 1).append(": ");
|
||||||
|
sb.append(subEx);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(PrintStream ps) {
|
||||||
|
if (ObjectUtils.isEmpty(this.messageExceptions)) {
|
||||||
|
super.printStackTrace(ps);
|
||||||
|
} else {
|
||||||
|
ps.println(super.toString() + "; message exception details (" +
|
||||||
|
this.messageExceptions.length + ") are:");
|
||||||
|
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||||
|
Exception subEx = this.messageExceptions[i];
|
||||||
|
ps.println("Failed message " + (i + 1) + ":");
|
||||||
|
subEx.printStackTrace(ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void printStackTrace(PrintWriter pw) {
|
||||||
|
if (ObjectUtils.isEmpty(this.messageExceptions)) {
|
||||||
|
super.printStackTrace(pw);
|
||||||
|
} else {
|
||||||
|
pw.println(super.toString() + "; message exception details (" +
|
||||||
|
this.messageExceptions.length + ") are:");
|
||||||
|
for (int i = 0; i < this.messageExceptions.length; i++) {
|
||||||
|
Exception subEx = this.messageExceptions[i];
|
||||||
|
pw.println("Failed message " + (i + 1) + ":");
|
||||||
|
subEx.printStackTrace(pw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.JavaMailSender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a strategy for sending simple mails. Can be
|
||||||
|
* implemented for a variety of mailing systems due to the simple requirements.
|
||||||
|
* For richer functionality like MIME messages, consider JavaMailSender.
|
||||||
|
*
|
||||||
|
* <p>Allows for easy testing of clients, as it does not depend on JavaMail's
|
||||||
|
* infrastructure classes: no mocking of JavaMail Session or Transport necessary.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see JavaMailSender
|
||||||
|
* @since 10.09.2003
|
||||||
|
*/
|
||||||
|
public interface MailSender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given simple mail message.
|
||||||
|
*
|
||||||
|
* @param simpleMessage the message to send
|
||||||
|
* @throws MailParseException in case of failure when parsing the message
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending the message
|
||||||
|
*/
|
||||||
|
void send(SimpleMailMessage simpleMessage) throws MailException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given array of simple mail messages in batch.
|
||||||
|
*
|
||||||
|
* @param simpleMessages the messages to send
|
||||||
|
* @throws MailParseException in case of failure when parsing a message
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending a message
|
||||||
|
*/
|
||||||
|
void send(SimpleMailMessage... simpleMessages) throws MailException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,270 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.JavaMailSender;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.MimeMailMessage;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.MimeMessageHelper;
|
||||||
|
import com.simaek.notify.email.embedded.mail.javamail.MimeMessagePreparator;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Models a simple mail message, including data such as the from, to, cc, subject,
|
||||||
|
* and text fields.
|
||||||
|
*
|
||||||
|
* <p>Consider {@code JavaMailSender} and JavaMail {@code MimeMessages} for creating
|
||||||
|
* more sophisticated messages, for example messages with attachments, special
|
||||||
|
* character encodings, or personal names that accompany mail addresses.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see MailSender
|
||||||
|
* @see JavaMailSender
|
||||||
|
* @see MimeMessagePreparator
|
||||||
|
* @see MimeMessageHelper
|
||||||
|
* @see MimeMailMessage
|
||||||
|
* @since 10.09.2003
|
||||||
|
*/
|
||||||
|
public class SimpleMailMessage implements MailMessage, Serializable {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String from;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String replyTo;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String[] to;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String[] cc;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String[] bcc;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Date sentDate;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String subject;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code SimpleMailMessage}.
|
||||||
|
*/
|
||||||
|
public SimpleMailMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor for creating a new {@code SimpleMailMessage} from the state
|
||||||
|
* of an existing {@code SimpleMailMessage} instance.
|
||||||
|
*/
|
||||||
|
public SimpleMailMessage(SimpleMailMessage original) {
|
||||||
|
Assert.notNull(original, "'original' message argument must not be null");
|
||||||
|
this.from = original.getFrom();
|
||||||
|
this.replyTo = original.getReplyTo();
|
||||||
|
this.to = copyOrNull(original.getTo());
|
||||||
|
this.cc = copyOrNull(original.getCc());
|
||||||
|
this.bcc = copyOrNull(original.getBcc());
|
||||||
|
this.sentDate = original.getSentDate();
|
||||||
|
this.subject = original.getSubject();
|
||||||
|
this.text = original.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFrom(String from) {
|
||||||
|
this.from = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getFrom() {
|
||||||
|
return this.from;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReplyTo(String replyTo) {
|
||||||
|
this.replyTo = replyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getReplyTo() {
|
||||||
|
return this.replyTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTo(String to) {
|
||||||
|
this.to = new String[]{to};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTo(String... to) {
|
||||||
|
this.to = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String[] getTo() {
|
||||||
|
return this.to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCc(String cc) {
|
||||||
|
this.cc = new String[]{cc};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCc(String... cc) {
|
||||||
|
this.cc = cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String[] getCc() {
|
||||||
|
return this.cc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBcc(String bcc) {
|
||||||
|
this.bcc = new String[]{bcc};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBcc(String... bcc) {
|
||||||
|
this.bcc = bcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String[] getBcc() {
|
||||||
|
return this.bcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSentDate(Date sentDate) {
|
||||||
|
this.sentDate = sentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Date getSentDate() {
|
||||||
|
return this.sentDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSubject(String subject) {
|
||||||
|
this.subject = subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getSubject() {
|
||||||
|
return this.subject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getText() {
|
||||||
|
return this.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy the contents of this message to the given target message.
|
||||||
|
*
|
||||||
|
* @param target the {@code MailMessage} to copy to
|
||||||
|
*/
|
||||||
|
public void copyTo(MailMessage target) {
|
||||||
|
Assert.notNull(target, "'target' MailMessage must not be null");
|
||||||
|
if (getFrom() != null) {
|
||||||
|
target.setFrom(getFrom());
|
||||||
|
}
|
||||||
|
if (getReplyTo() != null) {
|
||||||
|
target.setReplyTo(getReplyTo());
|
||||||
|
}
|
||||||
|
if (getTo() != null) {
|
||||||
|
target.setTo(copy(getTo()));
|
||||||
|
}
|
||||||
|
if (getCc() != null) {
|
||||||
|
target.setCc(copy(getCc()));
|
||||||
|
}
|
||||||
|
if (getBcc() != null) {
|
||||||
|
target.setBcc(copy(getBcc()));
|
||||||
|
}
|
||||||
|
if (getSentDate() != null) {
|
||||||
|
target.setSentDate(getSentDate());
|
||||||
|
}
|
||||||
|
if (getSubject() != null) {
|
||||||
|
target.setSubject(getSubject());
|
||||||
|
}
|
||||||
|
if (getText() != null) {
|
||||||
|
target.setText(getText());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(other instanceof SimpleMailMessage)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SimpleMailMessage otherMessage = (SimpleMailMessage) other;
|
||||||
|
return (ObjectUtils.nullSafeEquals(this.from, otherMessage.from) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.replyTo, otherMessage.replyTo) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.to, otherMessage.to) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.cc, otherMessage.cc) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.bcc, otherMessage.bcc) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.sentDate, otherMessage.sentDate) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.subject, otherMessage.subject) &&
|
||||||
|
ObjectUtils.nullSafeEquals(this.text, otherMessage.text));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hashCode = ObjectUtils.nullSafeHashCode(this.from);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.replyTo);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.to);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.cc);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.bcc);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.sentDate);
|
||||||
|
hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.subject);
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder("SimpleMailMessage: ");
|
||||||
|
sb.append("from=").append(this.from).append("; ");
|
||||||
|
sb.append("replyTo=").append(this.replyTo).append("; ");
|
||||||
|
sb.append("to=").append(StringUtils.arrayToCommaDelimitedString(this.to)).append("; ");
|
||||||
|
sb.append("cc=").append(StringUtils.arrayToCommaDelimitedString(this.cc)).append("; ");
|
||||||
|
sb.append("bcc=").append(StringUtils.arrayToCommaDelimitedString(this.bcc)).append("; ");
|
||||||
|
sb.append("sentDate=").append(this.sentDate).append("; ");
|
||||||
|
sb.append("subject=").append(this.subject).append("; ");
|
||||||
|
sb.append("text=").append(this.text);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static String[] copyOrNull(@Nullable String[] state) {
|
||||||
|
if (state == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return copy(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] copy(String[] state) {
|
||||||
|
return state.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,159 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import javax.activation.FileTypeMap;
|
||||||
|
import javax.activation.MimetypesFileTypeMap;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring-configurable {@code FileTypeMap} implementation that will read
|
||||||
|
* MIME type to file extension mappings from a standard JavaMail MIME type
|
||||||
|
* mapping file, using a standard {@code MimetypesFileTypeMap} underneath.
|
||||||
|
*
|
||||||
|
* <p>The mapping file should be in the following format, as specified by the
|
||||||
|
* Java Activation Framework:
|
||||||
|
*
|
||||||
|
* <pre class="code">
|
||||||
|
* # map text/html to .htm and .html files
|
||||||
|
* text/html html htm HTML HTM</pre>
|
||||||
|
* <p>
|
||||||
|
* Lines starting with {@code #} are treated as comments and are ignored. All
|
||||||
|
* other lines are treated as mappings. Each mapping line should contain the MIME
|
||||||
|
* type as the first entry and then each file extension to map to that MIME type
|
||||||
|
* as subsequent entries. Each entry is separated by spaces or tabs.
|
||||||
|
*
|
||||||
|
* <p>By default, the mappings in the {@code mime.types} file located in the
|
||||||
|
* same package as this class are used, which cover many common file extensions
|
||||||
|
* (in contrast to the out-of-the-box mappings in {@code activation.jar}).
|
||||||
|
* This can be overridden using the {@code mappingLocation} property.
|
||||||
|
*
|
||||||
|
* <p>Additional mappings can be added via the {@code mappings} bean property,
|
||||||
|
* as lines that follow the {@code mime.types} file format.
|
||||||
|
*
|
||||||
|
* @author Rob Harrop
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see #setMappingLocation
|
||||||
|
* @see #setMappings
|
||||||
|
* @see MimetypesFileTypeMap
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
public class ConfigurableMimeFileTypeMap extends FileTypeMap {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code Resource} to load the mapping file from.
|
||||||
|
*/
|
||||||
|
private Resource mappingLocation = new ClassPathResource("mime.types", getClass());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure additional mappings.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private String[] mappings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The delegate FileTypeMap, compiled from the mappings in the mapping file
|
||||||
|
* and the entries in the {@code mappings} property.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private FileTypeMap fileTypeMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify the {@code Resource} from which mappings are loaded.
|
||||||
|
* <p>Needs to follow the {@code mime.types} file format, as specified
|
||||||
|
* by the Java Activation Framework, containing lines such as:<br>
|
||||||
|
* {@code text/html html htm HTML HTM}
|
||||||
|
*/
|
||||||
|
public void setMappingLocation(Resource mappingLocation) {
|
||||||
|
this.mappingLocation = mappingLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specify additional MIME type mappings as lines that follow the
|
||||||
|
* {@code mime.types} file format, as specified by the
|
||||||
|
* Java Activation Framework. For example:<br>
|
||||||
|
* {@code text/html html htm HTML HTM}
|
||||||
|
*/
|
||||||
|
public void setMappings(String... mappings) {
|
||||||
|
this.mappings = mappings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the delegate FileTypeMap, compiled from the mappings in the mapping file
|
||||||
|
* and the entries in the {@code mappings} property.
|
||||||
|
*
|
||||||
|
* @see #setMappingLocation
|
||||||
|
* @see #setMappings
|
||||||
|
* @see #createFileTypeMap
|
||||||
|
*/
|
||||||
|
protected final FileTypeMap getFileTypeMap() {
|
||||||
|
if (this.fileTypeMap == null) {
|
||||||
|
try {
|
||||||
|
this.fileTypeMap = createFileTypeMap(this.mappingLocation, this.mappings);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Could not load specified MIME type mapping file: " + this.mappingLocation, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.fileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile a {@link FileTypeMap} from the mappings in the given mapping file
|
||||||
|
* and the given mapping entries.
|
||||||
|
* <p>The default implementation creates an Activation Framework {@link MimetypesFileTypeMap},
|
||||||
|
* passing in an InputStream from the mapping resource (if any) and registering
|
||||||
|
* the mapping lines programmatically.
|
||||||
|
*
|
||||||
|
* @param mappingLocation a {@code mime.types} mapping resource (can be {@code null})
|
||||||
|
* @param mappings an array of MIME type mapping lines (can be {@code null})
|
||||||
|
* @return the compiled FileTypeMap
|
||||||
|
* @throws IOException if resource access failed
|
||||||
|
* @see MimetypesFileTypeMap#MimetypesFileTypeMap(InputStream)
|
||||||
|
* @see MimetypesFileTypeMap#addMimeTypes(String)
|
||||||
|
*/
|
||||||
|
protected FileTypeMap createFileTypeMap(@Nullable Resource mappingLocation, @Nullable String[] mappings) throws IOException {
|
||||||
|
MimetypesFileTypeMap fileTypeMap = null;
|
||||||
|
if (mappingLocation != null) {
|
||||||
|
try (InputStream is = mappingLocation.getInputStream()) {
|
||||||
|
fileTypeMap = new MimetypesFileTypeMap(is);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileTypeMap = new MimetypesFileTypeMap();
|
||||||
|
}
|
||||||
|
if (mappings != null) {
|
||||||
|
for (String mapping : mappings) {
|
||||||
|
fileTypeMap.addMimeTypes(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates to the underlying FileTypeMap.
|
||||||
|
*
|
||||||
|
* @see #getFileTypeMap()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getContentType(File file) {
|
||||||
|
return getFileTypeMap().getContentType(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates to the underlying FileTypeMap.
|
||||||
|
*
|
||||||
|
* @see #getFileTypeMap()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getContentType(String fileName) {
|
||||||
|
return getFileTypeMap().getContentType(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2014 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import javax.mail.internet.AddressException;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
import java.beans.PropertyEditorSupport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Editor for {@code java.mail.internet.InternetAddress},
|
||||||
|
* to directly populate an InternetAddress property.
|
||||||
|
*
|
||||||
|
* <p>Expects the same syntax as InternetAddress's constructor with
|
||||||
|
* a String argument. Converts empty Strings into null values.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 1.2.3
|
||||||
|
* @see InternetAddress
|
||||||
|
*/
|
||||||
|
public class InternetAddressEditor extends PropertyEditorSupport {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAsText(String text) throws IllegalArgumentException {
|
||||||
|
if (StringUtils.hasText(text)) {
|
||||||
|
try {
|
||||||
|
setValue(new InternetAddress(text));
|
||||||
|
}
|
||||||
|
catch (AddressException ex) {
|
||||||
|
throw new IllegalArgumentException("Could not parse mail address: " + ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setValue(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAsText() {
|
||||||
|
InternetAddress value = (InternetAddress) getValue();
|
||||||
|
return (value != null ? value.toUnicodeString() : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.*;
|
||||||
|
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extended {@link MailSender} interface for JavaMail,
|
||||||
|
* supporting MIME messages both as direct arguments and through preparation
|
||||||
|
* callbacks. Typically used in conjunction with the {@link MimeMessageHelper}
|
||||||
|
* class for convenient creation of JavaMail {@link MimeMessage MimeMessages},
|
||||||
|
* including attachments etc.
|
||||||
|
*
|
||||||
|
* <p>Clients should talk to the mail sender through this interface if they need
|
||||||
|
* mail functionality beyond {@link SimpleMailMessage}.
|
||||||
|
* The production implementation is {@link JavaMailSenderImpl}; for testing,
|
||||||
|
* mocks can be created based on this interface. Clients will typically receive
|
||||||
|
* the JavaMailSender reference through dependency injection.
|
||||||
|
*
|
||||||
|
* <p>The recommended way of using this interface is the {@link MimeMessagePreparator}
|
||||||
|
* mechanism, possibly using a {@link MimeMessageHelper} for populating the message.
|
||||||
|
* See {@link MimeMessageHelper MimeMessageHelper's javadoc} for an example.
|
||||||
|
*
|
||||||
|
* <p>The entire JavaMail {@link javax.mail.Session} management is abstracted
|
||||||
|
* by the JavaMailSender. Client code should not deal with a Session in any way,
|
||||||
|
* rather leave the entire JavaMail configuration and resource handling to the
|
||||||
|
* JavaMailSender implementation. This also increases testability.
|
||||||
|
*
|
||||||
|
* <p>A JavaMailSender client is not as easy to test as a plain
|
||||||
|
* {@link MailSender} client, but still straightforward
|
||||||
|
* compared to traditional JavaMail code: Just let {@link #createMimeMessage()}
|
||||||
|
* return a plain {@link MimeMessage} created with a
|
||||||
|
* {@code Session.getInstance(new Properties())} call, and check the passed-in
|
||||||
|
* messages in your mock implementations of the various {@code send} methods.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see MimeMessage
|
||||||
|
* @see javax.mail.Session
|
||||||
|
* @see JavaMailSenderImpl
|
||||||
|
* @see MimeMessagePreparator
|
||||||
|
* @see MimeMessageHelper
|
||||||
|
* @since 07.10.2003
|
||||||
|
*/
|
||||||
|
public interface JavaMailSender extends MailSender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new JavaMail MimeMessage for the underlying JavaMail Session
|
||||||
|
* of this sender. Needs to be called to create MimeMessage instances
|
||||||
|
* that can be prepared by the client and passed to send(MimeMessage).
|
||||||
|
*
|
||||||
|
* @return the new MimeMessage instance
|
||||||
|
* @see #send(MimeMessage)
|
||||||
|
* @see #send(MimeMessage[])
|
||||||
|
*/
|
||||||
|
MimeMessage createMimeMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new JavaMail MimeMessage for the underlying JavaMail Session
|
||||||
|
* of this sender, using the given input stream as the message source.
|
||||||
|
*
|
||||||
|
* @param contentStream the raw MIME input stream for the message
|
||||||
|
* @return the new MimeMessage instance
|
||||||
|
* @throws MailParseException in case of message creation failure
|
||||||
|
*/
|
||||||
|
MimeMessage createMimeMessage(InputStream contentStream) throws MailException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given JavaMail MIME message.
|
||||||
|
* The message needs to have been created with {@link #createMimeMessage()}.
|
||||||
|
*
|
||||||
|
* @param mimeMessage message to send
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending the message
|
||||||
|
* @see #createMimeMessage
|
||||||
|
*/
|
||||||
|
void send(MimeMessage mimeMessage) throws MailException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given array of JavaMail MIME messages in batch.
|
||||||
|
* The messages need to have been created with {@link #createMimeMessage()}.
|
||||||
|
*
|
||||||
|
* @param mimeMessages messages to send
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending a message
|
||||||
|
* @see #createMimeMessage
|
||||||
|
*/
|
||||||
|
void send(MimeMessage... mimeMessages) throws MailException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the JavaMail MIME message prepared by the given MimeMessagePreparator.
|
||||||
|
* <p>Alternative way to prepare MimeMessage instances, instead of
|
||||||
|
* {@link #createMimeMessage()} and {@link #send(MimeMessage)} calls.
|
||||||
|
* Takes care of proper exception conversion.
|
||||||
|
*
|
||||||
|
* @param mimeMessagePreparator the preparator to use
|
||||||
|
* @throws MailPreparationException in case of failure when preparing the message
|
||||||
|
* @throws MailParseException in case of failure when parsing the message
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending the message
|
||||||
|
*/
|
||||||
|
void send(MimeMessagePreparator mimeMessagePreparator) throws MailException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the JavaMail MIME messages prepared by the given MimeMessagePreparators.
|
||||||
|
* <p>Alternative way to prepare MimeMessage instances, instead of
|
||||||
|
* {@link #createMimeMessage()} and {@link #send(MimeMessage[])} calls.
|
||||||
|
* Takes care of proper exception conversion.
|
||||||
|
*
|
||||||
|
* @param mimeMessagePreparators the preparator to use
|
||||||
|
* @throws MailPreparationException in case of failure when preparing a message
|
||||||
|
* @throws MailParseException in case of failure when parsing a message
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending a message
|
||||||
|
*/
|
||||||
|
void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,507 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.*;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import javax.activation.FileTypeMap;
|
||||||
|
import javax.mail.*;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Production implementation of the {@link JavaMailSender} interface,
|
||||||
|
* supporting both JavaMail {@link MimeMessage MimeMessages} and Spring
|
||||||
|
* {@link SimpleMailMessage SimpleMailMessages}. Can also be used as a
|
||||||
|
* plain {@link MailSender} implementation.
|
||||||
|
*
|
||||||
|
* <p>Allows for defining all settings locally as bean properties.
|
||||||
|
* Alternatively, a pre-configured JavaMail {@link Session} can be
|
||||||
|
* specified, possibly pulled from an application server's JNDI environment.
|
||||||
|
*
|
||||||
|
* <p>Non-default properties in this object will always override the settings
|
||||||
|
* in the JavaMail {@code Session}. Note that if overriding all values locally,
|
||||||
|
* there is no added value in setting a pre-configured {@code Session}.
|
||||||
|
*
|
||||||
|
* @author Dmitriy Kopylenko
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see MimeMessage
|
||||||
|
* @see Session
|
||||||
|
* @see #setSession
|
||||||
|
* @see #setJavaMailProperties
|
||||||
|
* @see #setHost
|
||||||
|
* @see #setPort
|
||||||
|
* @see #setUsername
|
||||||
|
* @see #setPassword
|
||||||
|
* @since 10.09.2003
|
||||||
|
*/
|
||||||
|
public class JavaMailSenderImpl implements JavaMailSender {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default protocol: 'smtp'.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_PROTOCOL = "smtp";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default port: -1.
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_PORT = -1;
|
||||||
|
|
||||||
|
private static final String HEADER_MESSAGE_ID = "Message-ID";
|
||||||
|
|
||||||
|
|
||||||
|
private Properties javaMailProperties = new Properties();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String protocol;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String host;
|
||||||
|
|
||||||
|
private int port = DEFAULT_PORT;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String defaultEncoding;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private FileTypeMap defaultFileTypeMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the {@code JavaMailSenderImpl} class.
|
||||||
|
* <p>Initializes the {@link #setDefaultFileTypeMap "defaultFileTypeMap"}
|
||||||
|
* property with a default {@link ConfigurableMimeFileTypeMap}.
|
||||||
|
*/
|
||||||
|
public JavaMailSenderImpl() {
|
||||||
|
ConfigurableMimeFileTypeMap fileTypeMap = new ConfigurableMimeFileTypeMap();
|
||||||
|
// fileTypeMap.afterPropertiesSet();
|
||||||
|
this.defaultFileTypeMap = fileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set JavaMail properties for the {@code Session}.
|
||||||
|
* <p>A new {@code Session} will be created with those properties.
|
||||||
|
* Use either this method or {@link #setSession}, but not both.
|
||||||
|
* <p>Non-default properties in this instance will override given
|
||||||
|
* JavaMail properties.
|
||||||
|
*/
|
||||||
|
public void setJavaMailProperties(Properties javaMailProperties) {
|
||||||
|
this.javaMailProperties = javaMailProperties;
|
||||||
|
synchronized (this) {
|
||||||
|
this.session = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow {code Map} access to the JavaMail properties of this sender,
|
||||||
|
* with the option to add or override specific entries.
|
||||||
|
* <p>Useful for specifying entries directly, for example via
|
||||||
|
* {code javaMailProperties[mail.smtp.auth]}.
|
||||||
|
*/
|
||||||
|
public Properties getJavaMailProperties() {
|
||||||
|
return this.javaMailProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the JavaMail {@code Session}, possibly pulled from JNDI.
|
||||||
|
* <p>Default is a new {@code Session} without defaults, that is
|
||||||
|
* completely configured via this instance's properties.
|
||||||
|
* <p>If using a pre-configured {@code Session}, non-default properties
|
||||||
|
* in this instance will override the settings in the {@code Session}.
|
||||||
|
*
|
||||||
|
* @see #setJavaMailProperties
|
||||||
|
*/
|
||||||
|
public synchronized void setSession(Session session) {
|
||||||
|
Assert.notNull(session, "Session must not be null");
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the JavaMail {@code Session},
|
||||||
|
* lazily initializing it if it hasn't been specified explicitly.
|
||||||
|
*/
|
||||||
|
public synchronized Session getSession() {
|
||||||
|
if (this.session == null) {
|
||||||
|
this.session = Session.getInstance(this.javaMailProperties);
|
||||||
|
}
|
||||||
|
return this.session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mail protocol. Default is "smtp".
|
||||||
|
*/
|
||||||
|
public void setProtocol(@Nullable String protocol) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the mail protocol.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getProtocol() {
|
||||||
|
return this.protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mail server host, typically an SMTP host.
|
||||||
|
* <p>Default is the default host of the underlying JavaMail Session.
|
||||||
|
*/
|
||||||
|
public void setHost(@Nullable String host) {
|
||||||
|
this.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the mail server host.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getHost() {
|
||||||
|
return this.host;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the mail server port.
|
||||||
|
* <p>Default is {@link #DEFAULT_PORT}, letting JavaMail use the default
|
||||||
|
* SMTP port (25).
|
||||||
|
*/
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the mail server port.
|
||||||
|
*/
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the username for the account at the mail host, if any.
|
||||||
|
* <p>Note that the underlying JavaMail {@code Session} has to be
|
||||||
|
* configured with the property {@code "mail.smtp.auth"} set to
|
||||||
|
* {@code true}, else the specified username will not be sent to the
|
||||||
|
* mail server by the JavaMail runtime. If you are not explicitly passing
|
||||||
|
* in a {@code Session} to use, simply specify this setting via
|
||||||
|
* {@link #setJavaMailProperties}.
|
||||||
|
*
|
||||||
|
* @see #setSession
|
||||||
|
* @see #setPassword
|
||||||
|
*/
|
||||||
|
public void setUsername(@Nullable String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the username for the account at the mail host.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getUsername() {
|
||||||
|
return this.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the password for the account at the mail host, if any.
|
||||||
|
* <p>Note that the underlying JavaMail {@code Session} has to be
|
||||||
|
* configured with the property {@code "mail.smtp.auth"} set to
|
||||||
|
* {@code true}, else the specified password will not be sent to the
|
||||||
|
* mail server by the JavaMail runtime. If you are not explicitly passing
|
||||||
|
* in a {@code Session} to use, simply specify this setting via
|
||||||
|
* {@link #setJavaMailProperties}.
|
||||||
|
*
|
||||||
|
* @see #setSession
|
||||||
|
* @see #setUsername
|
||||||
|
*/
|
||||||
|
public void setPassword(@Nullable String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the password for the account at the mail host.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default encoding to use for {@link MimeMessage MimeMessages}
|
||||||
|
* created by this instance.
|
||||||
|
* <p>Such an encoding will be auto-detected by {@link MimeMessageHelper}.
|
||||||
|
*/
|
||||||
|
public void setDefaultEncoding(@Nullable String defaultEncoding) {
|
||||||
|
this.defaultEncoding = defaultEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default encoding for {@link MimeMessage MimeMessages},
|
||||||
|
* or {@code null} if none.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDefaultEncoding() {
|
||||||
|
return this.defaultEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default Java Activation {@link FileTypeMap} to use for
|
||||||
|
* {@link MimeMessage MimeMessages} created by this instance.
|
||||||
|
* <p>A {@code FileTypeMap} specified here will be autodetected by
|
||||||
|
* {@link MimeMessageHelper}, avoiding the need to specify the
|
||||||
|
* {@code FileTypeMap} for each {@code MimeMessageHelper} instance.
|
||||||
|
* <p>For example, you can specify a custom instance of Spring's
|
||||||
|
* {@link ConfigurableMimeFileTypeMap} here. If not explicitly specified,
|
||||||
|
* a default {@code ConfigurableMimeFileTypeMap} will be used, containing
|
||||||
|
* an extended set of MIME type mappings (as defined by the
|
||||||
|
* {@code mime.types} file contained in the Spring jar).
|
||||||
|
*
|
||||||
|
* @see MimeMessageHelper#setFileTypeMap
|
||||||
|
*/
|
||||||
|
public void setDefaultFileTypeMap(@Nullable FileTypeMap defaultFileTypeMap) {
|
||||||
|
this.defaultFileTypeMap = defaultFileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default Java Activation {@link FileTypeMap} for
|
||||||
|
* {@link MimeMessage MimeMessages}, or {@code null} if none.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public FileTypeMap getDefaultFileTypeMap() {
|
||||||
|
return this.defaultFileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Implementation of MailSender
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(SimpleMailMessage simpleMessage) throws MailException {
|
||||||
|
send(new SimpleMailMessage[]{simpleMessage});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(SimpleMailMessage... simpleMessages) throws MailException {
|
||||||
|
List<MimeMessage> mimeMessages = new ArrayList<>(simpleMessages.length);
|
||||||
|
for (SimpleMailMessage simpleMessage : simpleMessages) {
|
||||||
|
MimeMailMessage message = new MimeMailMessage(createMimeMessage());
|
||||||
|
simpleMessage.copyTo(message);
|
||||||
|
mimeMessages.add(message.getMimeMessage());
|
||||||
|
}
|
||||||
|
doSend(mimeMessages.toArray(new MimeMessage[0]), simpleMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Implementation of JavaMailSender
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implementation creates a SmartMimeMessage, holding the specified
|
||||||
|
* default encoding and default FileTypeMap. This special defaults-carrying
|
||||||
|
* message will be autodetected by {@link MimeMessageHelper}, which will use
|
||||||
|
* the carried encoding and FileTypeMap unless explicitly overridden.
|
||||||
|
*
|
||||||
|
* @see #setDefaultEncoding
|
||||||
|
* @see #setDefaultFileTypeMap
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public MimeMessage createMimeMessage() {
|
||||||
|
return new SmartMimeMessage(getSession(), getDefaultEncoding(), getDefaultFileTypeMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MimeMessage createMimeMessage(InputStream contentStream) throws MailException {
|
||||||
|
try {
|
||||||
|
return new MimeMessage(getSession(), contentStream);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new MailParseException("Could not parse raw MIME content", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(MimeMessage mimeMessage) throws MailException {
|
||||||
|
send(new MimeMessage[]{mimeMessage});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(MimeMessage... mimeMessages) throws MailException {
|
||||||
|
doSend(mimeMessages, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(MimeMessagePreparator mimeMessagePreparator) throws MailException {
|
||||||
|
send(new MimeMessagePreparator[]{mimeMessagePreparator});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(MimeMessagePreparator... mimeMessagePreparators) throws MailException {
|
||||||
|
try {
|
||||||
|
List<MimeMessage> mimeMessages = new ArrayList<>(mimeMessagePreparators.length);
|
||||||
|
for (MimeMessagePreparator preparator : mimeMessagePreparators) {
|
||||||
|
MimeMessage mimeMessage = createMimeMessage();
|
||||||
|
preparator.prepare(mimeMessage);
|
||||||
|
mimeMessages.add(mimeMessage);
|
||||||
|
}
|
||||||
|
send(mimeMessages.toArray(new MimeMessage[0]));
|
||||||
|
} catch (MailException ex) {
|
||||||
|
throw ex;
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new MailPreparationException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that this instance can connect to the server that it is configured
|
||||||
|
* for. Throws a {@link MessagingException} if the connection attempt failed.
|
||||||
|
*/
|
||||||
|
public void testConnection() throws MessagingException {
|
||||||
|
Transport transport = null;
|
||||||
|
try {
|
||||||
|
transport = connectTransport();
|
||||||
|
} finally {
|
||||||
|
if (transport != null) {
|
||||||
|
transport.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually send the given array of MimeMessages via JavaMail.
|
||||||
|
*
|
||||||
|
* @param mimeMessages the MimeMessage objects to send
|
||||||
|
* @param originalMessages corresponding original message objects
|
||||||
|
* that the MimeMessages have been created from (with same array
|
||||||
|
* length and indices as the "mimeMessages" array), if any
|
||||||
|
* @throws MailAuthenticationException in case of authentication failure
|
||||||
|
* @throws MailSendException in case of failure when sending a message
|
||||||
|
*/
|
||||||
|
protected void doSend(MimeMessage[] mimeMessages, @Nullable Object[] originalMessages) throws MailException {
|
||||||
|
Map<Object, Exception> failedMessages = new LinkedHashMap<>();
|
||||||
|
Transport transport = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < mimeMessages.length; i++) {
|
||||||
|
|
||||||
|
// Check transport connection first...
|
||||||
|
if (transport == null || !transport.isConnected()) {
|
||||||
|
if (transport != null) {
|
||||||
|
try {
|
||||||
|
transport.close();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Ignore - we're reconnecting anyway
|
||||||
|
}
|
||||||
|
transport = null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
transport = connectTransport();
|
||||||
|
} catch (AuthenticationFailedException ex) {
|
||||||
|
throw new MailAuthenticationException(ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Effectively, all remaining messages failed...
|
||||||
|
for (int j = i; j < mimeMessages.length; j++) {
|
||||||
|
Object original = (originalMessages != null ? originalMessages[j] : mimeMessages[j]);
|
||||||
|
failedMessages.put(original, ex);
|
||||||
|
}
|
||||||
|
throw new MailSendException("Mail server connection failed", ex, failedMessages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send message via current transport...
|
||||||
|
MimeMessage mimeMessage = mimeMessages[i];
|
||||||
|
try {
|
||||||
|
if (mimeMessage.getSentDate() == null) {
|
||||||
|
mimeMessage.setSentDate(new Date());
|
||||||
|
}
|
||||||
|
String messageId = mimeMessage.getMessageID();
|
||||||
|
mimeMessage.saveChanges();
|
||||||
|
if (messageId != null) {
|
||||||
|
// Preserve explicitly specified message id...
|
||||||
|
mimeMessage.setHeader(HEADER_MESSAGE_ID, messageId);
|
||||||
|
}
|
||||||
|
Address[] addresses = mimeMessage.getAllRecipients();
|
||||||
|
transport.sendMessage(mimeMessage, (addresses != null ? addresses : new Address[0]));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
Object original = (originalMessages != null ? originalMessages[i] : mimeMessage);
|
||||||
|
failedMessages.put(original, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (transport != null) {
|
||||||
|
transport.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
if (!failedMessages.isEmpty()) {
|
||||||
|
throw new MailSendException("Failed to close server connection after message failures", ex,
|
||||||
|
failedMessages);
|
||||||
|
} else {
|
||||||
|
throw new MailSendException("Failed to close server connection after message sending", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!failedMessages.isEmpty()) {
|
||||||
|
throw new MailSendException(failedMessages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain and connect a Transport from the underlying JavaMail Session,
|
||||||
|
* passing in the specified host, port, username, and password.
|
||||||
|
*
|
||||||
|
* @return the connected Transport object
|
||||||
|
* @throws MessagingException if the connect attempt failed
|
||||||
|
* @see #getTransport
|
||||||
|
* @see #getHost()
|
||||||
|
* @see #getPort()
|
||||||
|
* @see #getUsername()
|
||||||
|
* @see #getPassword()
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
protected Transport connectTransport() throws MessagingException {
|
||||||
|
String username = getUsername();
|
||||||
|
String password = getPassword();
|
||||||
|
if ("".equals(username)) { // probably from a placeholder
|
||||||
|
username = null;
|
||||||
|
if ("".equals(password)) { // in conjunction with "" username, this means no password to use
|
||||||
|
password = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Transport transport = getTransport(getSession());
|
||||||
|
transport.connect(getHost(), getPort(), username, password);
|
||||||
|
return transport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a Transport object from the given JavaMail Session,
|
||||||
|
* using the configured protocol.
|
||||||
|
* <p>Can be overridden in subclasses, e.g. to return a mock Transport object.
|
||||||
|
*
|
||||||
|
* @see Session#getTransport(String)
|
||||||
|
* @see #getSession()
|
||||||
|
* @see #getProtocol()
|
||||||
|
*/
|
||||||
|
protected Transport getTransport(Session session) throws NoSuchProviderException {
|
||||||
|
String protocol = getProtocol();
|
||||||
|
if (protocol == null) {
|
||||||
|
protocol = session.getProperty("mail.transport.protocol");
|
||||||
|
if (protocol == null) {
|
||||||
|
protocol = DEFAULT_PROTOCOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return session.getTransport(protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import com.simaek.notify.email.embedded.mail.MailMessage;
|
||||||
|
import com.simaek.notify.email.embedded.mail.MailParseException;
|
||||||
|
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the MailMessage interface for a JavaMail MIME message,
|
||||||
|
* to let message population code interact with a simple message or a MIME
|
||||||
|
* message through a common interface.
|
||||||
|
*
|
||||||
|
* <p>Uses a MimeMessageHelper underneath. Can either be created with a
|
||||||
|
* MimeMessageHelper instance or with a JavaMail MimeMessage instance.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see MimeMessageHelper
|
||||||
|
* @see MimeMessage
|
||||||
|
* @since 1.1.5
|
||||||
|
*/
|
||||||
|
public class MimeMailMessage implements MailMessage {
|
||||||
|
|
||||||
|
private final MimeMessageHelper helper;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MimeMailMessage based on the given MimeMessageHelper.
|
||||||
|
*
|
||||||
|
* @param mimeMessageHelper the MimeMessageHelper
|
||||||
|
*/
|
||||||
|
public MimeMailMessage(MimeMessageHelper mimeMessageHelper) {
|
||||||
|
this.helper = mimeMessageHelper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new MimeMailMessage based on the given JavaMail MimeMessage.
|
||||||
|
*
|
||||||
|
* @param mimeMessage the JavaMail MimeMessage
|
||||||
|
*/
|
||||||
|
public MimeMailMessage(MimeMessage mimeMessage) {
|
||||||
|
this.helper = new MimeMessageHelper(mimeMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the MimeMessageHelper that this MimeMailMessage is based on.
|
||||||
|
*/
|
||||||
|
public final MimeMessageHelper getMimeMessageHelper() {
|
||||||
|
return this.helper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the JavaMail MimeMessage that this MimeMailMessage is based on.
|
||||||
|
*/
|
||||||
|
public final MimeMessage getMimeMessage() {
|
||||||
|
return this.helper.getMimeMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFrom(String from) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setFrom(from);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReplyTo(String replyTo) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setReplyTo(replyTo);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTo(String to) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setTo(to);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTo(String... to) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setTo(to);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCc(String cc) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setCc(cc);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCc(String... cc) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setCc(cc);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBcc(String bcc) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setBcc(bcc);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBcc(String... bcc) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setBcc(bcc);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSentDate(Date sentDate) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setSentDate(sentDate);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSubject(String subject) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setSubject(subject);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(String text) throws MailParseException {
|
||||||
|
try {
|
||||||
|
this.helper.setText(text);
|
||||||
|
} catch (MessagingException ex) {
|
||||||
|
throw new MailParseException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,39 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback interface for the preparation of JavaMail MIME messages.
|
||||||
|
*
|
||||||
|
* <p>The corresponding {@code send} methods of {@link JavaMailSender}
|
||||||
|
* will take care of the actual creation of a {@link MimeMessage} instance,
|
||||||
|
* and of proper exception conversion.
|
||||||
|
*
|
||||||
|
* <p>It is often convenient to use a {@link MimeMessageHelper} for populating
|
||||||
|
* the passed-in MimeMessage, in particular when working with attachments or
|
||||||
|
* special character encodings.
|
||||||
|
* See {@link MimeMessageHelper MimeMessageHelper's javadoc} for an example.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see JavaMailSender#send(MimeMessagePreparator)
|
||||||
|
* @see JavaMailSender#send(MimeMessagePreparator[])
|
||||||
|
* @see MimeMessageHelper
|
||||||
|
* @since 07.10.2003
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface MimeMessagePreparator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the given new MimeMessage instance.
|
||||||
|
*
|
||||||
|
* @param mimeMessage the message to prepare
|
||||||
|
* @throws javax.mail.MessagingException passing any exceptions thrown by MimeMessage
|
||||||
|
* methods through for automatic conversion to the MailException hierarchy
|
||||||
|
* @throws java.io.IOException passing any exceptions thrown by MimeMessage methods
|
||||||
|
* through for automatic conversion to the MailException hierarchy
|
||||||
|
* @throws Exception if mail preparation failed, for example when a
|
||||||
|
* FreeMarker template cannot be rendered for the mail text
|
||||||
|
*/
|
||||||
|
void prepare(MimeMessage mimeMessage) throws Exception;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
|
||||||
|
import javax.activation.FileTypeMap;
|
||||||
|
import javax.mail.Session;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special subclass of the standard JavaMail {@link MimeMessage}, carrying a
|
||||||
|
* default encoding to be used when populating the message and a default Java
|
||||||
|
* Activation {@link FileTypeMap} to be used for resolving attachment types.
|
||||||
|
*
|
||||||
|
* <p>Created by {@link JavaMailSenderImpl} in case of a specified default encoding
|
||||||
|
* and/or default FileTypeMap. Autodetected by {@link MimeMessageHelper}, which
|
||||||
|
* will use the carried encoding and FileTypeMap unless explicitly overridden.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @see JavaMailSenderImpl#createMimeMessage()
|
||||||
|
* @see MimeMessageHelper#getDefaultEncoding(MimeMessage)
|
||||||
|
* @see MimeMessageHelper#getDefaultFileTypeMap(MimeMessage)
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class SmartMimeMessage extends MimeMessage {
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final String defaultEncoding;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final FileTypeMap defaultFileTypeMap;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new SmartMimeMessage.
|
||||||
|
*
|
||||||
|
* @param session the JavaMail Session to create the message for
|
||||||
|
* @param defaultEncoding the default encoding, or {@code null} if none
|
||||||
|
* @param defaultFileTypeMap the default FileTypeMap, or {@code null} if none
|
||||||
|
*/
|
||||||
|
public SmartMimeMessage(
|
||||||
|
Session session, @Nullable String defaultEncoding, @Nullable FileTypeMap defaultFileTypeMap) {
|
||||||
|
|
||||||
|
super(session);
|
||||||
|
this.defaultEncoding = defaultEncoding;
|
||||||
|
this.defaultFileTypeMap = defaultFileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default encoding of this message, or {@code null} if none.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public final String getDefaultEncoding() {
|
||||||
|
return this.defaultEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the default FileTypeMap of this message, or {@code null} if none.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public final FileTypeMap getDefaultFileTypeMap() {
|
||||||
|
return this.defaultFileTypeMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,326 @@
|
|||||||
|
################################################################################
|
||||||
|
# Copyright 2002-2019 the original author or authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Defaults for the Java Activation Framework (revised).
|
||||||
|
#
|
||||||
|
# Modified extensions registered in this file:
|
||||||
|
# text/plain java c c++ cpp pl cc h
|
||||||
|
# image/png png
|
||||||
|
# image/svg+xml svg
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
text/html html htm HTML HTM
|
||||||
|
text/plain txt text TXT TEXT java c c++ cpp pl cc h
|
||||||
|
image/gif gif GIF
|
||||||
|
image/ief ief
|
||||||
|
image/jpeg jpeg jpg jpe JPG
|
||||||
|
image/tiff tiff tif
|
||||||
|
image/x-xwindowdump xwd
|
||||||
|
application/postscript ai eps ps
|
||||||
|
application/rtf rtf
|
||||||
|
application/x-tex tex
|
||||||
|
application/x-texinfo texinfo texi
|
||||||
|
application/x-troff t tr roff
|
||||||
|
audio/basic au
|
||||||
|
audio/midi midi mid
|
||||||
|
audio/x-aifc aifc
|
||||||
|
audio/x-aiff aif aiff
|
||||||
|
audio/x-mpeg mpeg mpg
|
||||||
|
audio/x-wav wav
|
||||||
|
video/mpeg mpeg mpg mpe
|
||||||
|
video/quicktime qt mov
|
||||||
|
video/x-msvideo avi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
#
|
||||||
|
# Additional file types adapted from
|
||||||
|
# http://sites.utoronto.ca/webdocs/HTMLdocs/Book/Book-3ed/appb/mimetype.html
|
||||||
|
# kindly re-licensed to Apache Software License 2.0 by Ian Graham.
|
||||||
|
#
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
# TEXT TYPES
|
||||||
|
|
||||||
|
text/x-speech talk
|
||||||
|
text/css css
|
||||||
|
text/csv csv
|
||||||
|
|
||||||
|
# IMAGE TYPES
|
||||||
|
|
||||||
|
# X-Windows bitmap (b/w)
|
||||||
|
image/x-xbitmap xbm
|
||||||
|
# X-Windows pixelmap (8-bit color)
|
||||||
|
image/x-xpixmap xpm
|
||||||
|
# Portable Network Graphics
|
||||||
|
image/png png
|
||||||
|
# Scalable Vector Graphics
|
||||||
|
image/svg+xml svg
|
||||||
|
# Image Exchange Format (RFC 1314)
|
||||||
|
image/ief ief
|
||||||
|
# RGB
|
||||||
|
image/rgb rgb
|
||||||
|
# Group III Fax (RFC 1494)
|
||||||
|
image/g3fax g3f
|
||||||
|
# X Windowdump format
|
||||||
|
image/x-xwindowdump xwd
|
||||||
|
# Macintosh PICT format
|
||||||
|
image/x-pict pict
|
||||||
|
# PPM (UNIX PPM package)
|
||||||
|
image/x-portable-pixmap ppm
|
||||||
|
# PGM (UNIX PPM package)
|
||||||
|
image/x-portable-graymap pgm
|
||||||
|
# PBM (UNIX PPM package)
|
||||||
|
image/x-portable-bitmap pbm
|
||||||
|
# PNM (UNIX PPM package)
|
||||||
|
image/x-portable-anymap pnm
|
||||||
|
# Microsoft Windows bitmap
|
||||||
|
image/x-ms-bmp bmp
|
||||||
|
# CMU raster
|
||||||
|
image/x-cmu-raster ras
|
||||||
|
# Kodak Photo-CD
|
||||||
|
image/x-photo-cd pcd
|
||||||
|
# Computer Graphics Metafile
|
||||||
|
image/cgm cgm
|
||||||
|
# CALS Type 1 or 2
|
||||||
|
image/x-cals mil cal
|
||||||
|
# Fractal Image Format (Iterated Systems)
|
||||||
|
image/fif fif
|
||||||
|
# QuickSilver active image (Micrografx)
|
||||||
|
image/x-mgx-dsf dsf
|
||||||
|
# CMX vector image (Corel)
|
||||||
|
image/x-cmx cmx
|
||||||
|
# Wavelet-compressed (Summus)
|
||||||
|
image/wavelet wi
|
||||||
|
# AutoCad Drawing (SoftSource)
|
||||||
|
image/vnd.dwg dwg
|
||||||
|
# AutoCad DXF file (SoftSource)
|
||||||
|
image/vnd.dxf dxf
|
||||||
|
# Simple Vector Format (SoftSource)
|
||||||
|
image/vnd.svf svf
|
||||||
|
|
||||||
|
# AUDIO/VOICE/MUSIC RELATED TYPES
|
||||||
|
|
||||||
|
# """basic""audio - 8-bit u-law PCM"
|
||||||
|
audio/basic au snd
|
||||||
|
# Macintosh audio format (AIpple)
|
||||||
|
audio/x-aiff aif aiff aifc
|
||||||
|
# Microsoft audio
|
||||||
|
audio/x-wav wav
|
||||||
|
# MPEG audio
|
||||||
|
audio/x-mpeg mpa abs mpega
|
||||||
|
# MPEG-2 audio
|
||||||
|
audio/x-mpeg-2 mp2a mpa2
|
||||||
|
# compressed speech (Echo Speech Corp.)
|
||||||
|
audio/echospeech es
|
||||||
|
# Toolvox speech audio (Voxware)
|
||||||
|
audio/voxware vox
|
||||||
|
# RapidTransit compressed audio (Fast Man)
|
||||||
|
application/fastman lcc
|
||||||
|
# Realaudio (Progressive Networks)
|
||||||
|
application/x-pn-realaudio ra ram
|
||||||
|
# MIDI music data
|
||||||
|
x-music/x-midi mmid
|
||||||
|
# Koan music data (SSeyo)
|
||||||
|
application/vnd.koan skp
|
||||||
|
# Speech synthesis data (MVP Solutions)
|
||||||
|
text/x-speech talk
|
||||||
|
|
||||||
|
# VIDEO TYPES
|
||||||
|
|
||||||
|
# MPEG video
|
||||||
|
video/mpeg mpeg mpg mpe
|
||||||
|
# MPEG-2 video
|
||||||
|
video/mpeg-2 mpv2 mp2v
|
||||||
|
# Macintosh Quicktime
|
||||||
|
video/quicktime qt mov
|
||||||
|
# Microsoft video
|
||||||
|
video/x-msvideo avi
|
||||||
|
# SGI Movie format
|
||||||
|
video/x-sgi-movie movie
|
||||||
|
# VDOlive streaming video (VDOnet)
|
||||||
|
video/vdo vdo
|
||||||
|
# Vivo streaming video (Vivo software)
|
||||||
|
video/vnd.vivo viv
|
||||||
|
|
||||||
|
# SPECIAL HTTP/WEB APPLICATION TYPES
|
||||||
|
|
||||||
|
# Proxy autoconfiguration (Netscape browsers)
|
||||||
|
application/x-ns-proxy-autoconfig pac
|
||||||
|
# Netscape Cooltalk chat data (Netscape)
|
||||||
|
x-conference/x-cooltalk ice
|
||||||
|
|
||||||
|
# TEXT-RELATED
|
||||||
|
|
||||||
|
# PostScript
|
||||||
|
application/postscript ai eps ps
|
||||||
|
# Microsoft Rich Text Format
|
||||||
|
application/rtf rtf
|
||||||
|
# Adobe Acrobat PDF
|
||||||
|
application/pdf pdf
|
||||||
|
# Maker Interchange Format (FrameMaker)
|
||||||
|
application/vnd.mif mif
|
||||||
|
# Troff document
|
||||||
|
application/x-troff t tr roff
|
||||||
|
# Troff document with MAN macros
|
||||||
|
application/x-troff-man man
|
||||||
|
# Troff document with ME macros
|
||||||
|
application/x-troff-me me
|
||||||
|
# Troff document with MS macros
|
||||||
|
application/x-troff-ms ms
|
||||||
|
# LaTeX document
|
||||||
|
application/x-latex latex
|
||||||
|
# Tex/LateX document
|
||||||
|
application/x-tex tex
|
||||||
|
# GNU TexInfo document
|
||||||
|
application/x-texinfo texinfo texi
|
||||||
|
# TeX dvi format
|
||||||
|
application/x-dvi dvi
|
||||||
|
# MS word document
|
||||||
|
application/msword doc DOC
|
||||||
|
# Office Document Architecture
|
||||||
|
application/oda oda
|
||||||
|
# Envoy Document
|
||||||
|
application/envoy evy
|
||||||
|
|
||||||
|
# ARCHIVE/COMPRESSED ARCHIVES
|
||||||
|
|
||||||
|
# Gnu tar format
|
||||||
|
application/x-gtar gtar
|
||||||
|
# 4.3BSD tar format
|
||||||
|
application/x-tar tar
|
||||||
|
# POSIX tar format
|
||||||
|
application/x-ustar ustar
|
||||||
|
# Old CPIO format
|
||||||
|
application/x-bcpio bcpio
|
||||||
|
# POSIX CPIO format
|
||||||
|
application/x-cpio cpio
|
||||||
|
# UNIX sh shell archive
|
||||||
|
application/x-shar shar
|
||||||
|
# DOS/PC - Pkzipped archive
|
||||||
|
application/zip zip
|
||||||
|
# Macintosh Binhexed archive
|
||||||
|
application/mac-binhex40 hqx
|
||||||
|
# Macintosh Stuffit Archive
|
||||||
|
application/x-stuffit sit sea
|
||||||
|
# Fractal Image Format
|
||||||
|
application/fractals fif
|
||||||
|
# "Binary UUencoded"
|
||||||
|
application/octet-stream bin uu
|
||||||
|
# PC executable
|
||||||
|
application/octet-stream exe
|
||||||
|
# "WAIS ""sources"""
|
||||||
|
application/x-wais-source src wsrc
|
||||||
|
# NCSA HDF data format
|
||||||
|
application/hdf hdf
|
||||||
|
|
||||||
|
# DOWNLOADABLE PROGRAM/SCRIPTS
|
||||||
|
|
||||||
|
# Javascript program
|
||||||
|
text/javascript js ls mocha
|
||||||
|
# UNIX bourne shell program
|
||||||
|
application/x-sh sh
|
||||||
|
# UNIX c-shell program
|
||||||
|
application/x-csh csh
|
||||||
|
# Perl program
|
||||||
|
application/x-perl pl
|
||||||
|
# Tcl (Tool Control Language) program
|
||||||
|
application/x-tcl tcl
|
||||||
|
|
||||||
|
# ANIMATION/MULTIMEDIA
|
||||||
|
|
||||||
|
# FutureSplash vector animation (FutureWave)
|
||||||
|
application/futuresplash spl
|
||||||
|
# mBED multimedia data (mBED)
|
||||||
|
application/mbedlet mbd
|
||||||
|
# PowerMedia multimedia (RadMedia)
|
||||||
|
application/x-rad-powermedia rad
|
||||||
|
|
||||||
|
# PRESENTATION
|
||||||
|
|
||||||
|
# PowerPoint presentation (Microsoft)
|
||||||
|
application/mspowerpoint ppz
|
||||||
|
# ASAP WordPower (Software Publishing Corp.)
|
||||||
|
application/x-asap asp
|
||||||
|
# Astound Web Player multimedia data (GoldDisk)
|
||||||
|
application/astound asn
|
||||||
|
|
||||||
|
# SPECIAL EMBEDDED OBJECT
|
||||||
|
|
||||||
|
# OLE script e.g. Visual Basic (Ncompass)
|
||||||
|
application/x-olescript axs
|
||||||
|
# OLE Object (Microsoft/NCompass)
|
||||||
|
application/x-oleobject ods
|
||||||
|
# OpenScape OLE/OCX objects (Business@Web)
|
||||||
|
x-form/x-openscape opp
|
||||||
|
# Visual Basic objects (Amara)
|
||||||
|
application/x-webbasic wba
|
||||||
|
# Specialized data entry forms (Alpha Software)
|
||||||
|
application/x-alpha-form frm
|
||||||
|
# client-server objects (Wayfarer Communications)
|
||||||
|
x-script/x-wfxclient wfx
|
||||||
|
|
||||||
|
# GENERAL APPLICATIONS
|
||||||
|
|
||||||
|
# Undefined binary data (often executable progs)
|
||||||
|
application/octet-stream exe com
|
||||||
|
# Pointcast news data (Pointcast)
|
||||||
|
application/x-pcn pcn
|
||||||
|
# Excel spreadsheet (Microsoft)
|
||||||
|
application/vnd.ms-excel xls
|
||||||
|
# PowerPoint (Microsoft)
|
||||||
|
application/vnd.ms-powerpoint ppt
|
||||||
|
# Microsoft Project (Microsoft)
|
||||||
|
application/vnd.ms-project mpp
|
||||||
|
# SourceView document (Dataware Electronics)
|
||||||
|
application/vnd.svd svd
|
||||||
|
# Net Install - software install (20/20 Software)
|
||||||
|
application/x-net-install ins
|
||||||
|
# Carbon Copy - remote control/access (Microcom)
|
||||||
|
application/ccv ccv
|
||||||
|
# Spreadsheets (Visual Components)
|
||||||
|
workbook/formulaone vts
|
||||||
|
|
||||||
|
# 2D/3D DATA/VIRTUAL REALITY TYPES
|
||||||
|
|
||||||
|
# VRML data file
|
||||||
|
x-world/x-vrml wrl vrml
|
||||||
|
# WIRL - VRML data (VREAM)
|
||||||
|
x-world/x-vream vrw
|
||||||
|
# Play3D 3d scene data (Play3D)
|
||||||
|
application/x-p3d p3d
|
||||||
|
# Viscape Interactive 3d world data (Superscape)
|
||||||
|
x-world/x-svr svr
|
||||||
|
# WebActive 3d data (Plastic Thought)
|
||||||
|
x-world/x-wvr wvr
|
||||||
|
# QuickDraw3D scene data (Apple)
|
||||||
|
x-world/x-3dmf 3dmf
|
||||||
|
|
||||||
|
# SCIENTIFIC/MATH/CAD TYPES
|
||||||
|
|
||||||
|
# Mathematica notebook
|
||||||
|
application/mathematica ma
|
||||||
|
# Computational meshes for numerical simulations
|
||||||
|
x-model/x-mesh msh
|
||||||
|
# Vis5D 5-dimensional data
|
||||||
|
application/vis5d v5d
|
||||||
|
# IGES models -- CAD/CAM (CGM) data
|
||||||
|
application/iges igs
|
||||||
|
# Autocad WHIP vector drawings
|
||||||
|
drawing/x-dwf dwf
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* JavaMail support for Spring's mail infrastructure.
|
||||||
|
* Provides an extended JavaMailSender interface and a MimeMessageHelper
|
||||||
|
* class for convenient population of a JavaMail MimeMessage.
|
||||||
|
*/
|
||||||
|
@NonNullApi
|
||||||
|
@NonNullFields
|
||||||
|
package com.simaek.notify.email.embedded.mail.javamail;
|
||||||
|
|
||||||
|
import org.springframework.lang.NonNullApi;
|
||||||
|
import org.springframework.lang.NonNullFields;
|
@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Spring's generic mail infrastructure.
|
||||||
|
* Concrete implementations are provided in the subpackages.
|
||||||
|
*/
|
||||||
|
@NonNullApi
|
||||||
|
@NonNullFields
|
||||||
|
package com.simaek.notify.email.embedded.mail;
|
||||||
|
|
||||||
|
import org.springframework.lang.NonNullApi;
|
||||||
|
import org.springframework.lang.NonNullFields;
|
Loading…
Reference in New Issue
Block a user