The goal is introduce a Mail API in the XWiki Platform to provide mail-related APIs.

History & Status

Use Cases

  • UC1: Be able to send multipart emails with any type of mime type content (html, text, vcalendar, etc)
  • UC2: Be able to get the mail content to send by rendering the content of an XWiki document (a.k.a a template)
  • UC3: Ensure the API is easy to use from Velocity (script service)
  • UC4: SMTP config should be able to be either specified explicitly or taken from XWiki configuration
  • UC5: Ability to easily embed images in the email (i.e. generate cid)
  • UC6: Ability to easily send an XWiki page by email (i.e. automatically embed images from that page in the email)
  • UC7: Allow both reading (POP3, IMAP) and sending (SMTP) emails, supporting SSL
  • UC8: Ability to send batch of emails

API Proposal

Scripting API

// Message creation, internally creates a JavaMail MimeMessage
$message = $services.mailSender.createMessage()
$message = $services.mailSender.createMessage(from, to, subject)
$message = $services.mailSender.createMessage(from, to, cc, bcc, subject)

// Set from, to, cc, bcc, subject
// Note that "from" is optional and if not specified, taken from Mail configuration
$message.setFrom("[email protected](mailto:[email protected])")

$message.addToRecipient("[email protected](mailto:[email protected])”)
$message.addToRecipients(["[email protected](mailto:[email protected])”, ...])

$message.addCcRecipient("[email protected](mailto:[email protected])”)
$message.addCcRecipients(["[email protected](mailto:[email protected])”, ...])

$message.addBccRecipient("[email protected](mailto:[email protected])”)
$message.addBccRecipients(["[email protected](mailto:[email protected])”, ...])

// Optional:
// Need a Converter implementation to convert from String to javax.mail.Message.RecipientType
$message.addRecipient("[email protected](mailto:[email protected])”, "to|bcc|cc")
$message.addRecipients("[email protected](mailto:[email protected])”, "to|bcc|cc")

$message.setSubject('Lorem Ipsum')

// Add the Content
// Note: the first parameter is a component hint. If no implementation corresponds to it, a default implementation is used which converts it to a Mime Type
// Note: We create by default a MultiPart("mixed") and the addPart() calls generate MultiPartBody added to this multipart.

// Add simple text to message
$message.addPart("text", "text message")

// Add simple text to message with a header
$message.addPart("text", "text message", {"headers" : { "Content-Transfer-Encoding" : "quoted-printable"}})

// Add simple HTML to message
$message.addPart("html", "html message")

// Add HTML + alternate text to message
$message.addPart("html", "html message", {"alternate" : "text message"})

// Add HTML + alternate text + embedded images + attachments to message
// Note: $attachments is of type List<Attachment>
$message.addPart("html", "html message", {"alternate" : "text message", "attachments" : $attachments})

// Add an XWiki attachment to message
$message.addPart("attachment", Attachment)

// And XWiki attachment to message from an Attachment reference
$message.addPart("attachment", AttachmentReference)

// Add all attachments found in the passed document reference to the message
$message.addPart("attachment", DocumentReference)

// Add all attachments to message
$message.addPart("attachments", List<Attachment>)

// Add a wiki page to message with embedded images and attachments
$message.addPart("document", DocumentReference)

// Generate the message from a template containing a XWiki.Mail object
$message.addPart("template", DocumentReference, {"velocityVariables" : { "var1" : "value1" }})

// Send Message now, asynchronously

// Send Message at some date

// Wait for the message to be sent

// Internally messages are added to a queue when send() is called and sent asynchronously by batches of N messages at a time. The number of messages to send in a batch is controlled by the Mail configuration in the Admin. We can imagine an API to get the mail configuration and override it temporarily:

$mailConfiguration = $services.mailSender.getConfiguration()

// And then:
$message.send(Date, MailConfiguration)

Java API

  • MailConfiguration component role with implementation taking the configuration values from the Administration
  • MimeBodyPart MimeBodyPartFactory.create(T source)
  • MimeMessageFactory to make it simple to create MimeMessage
  • MailSender component role to make the glue between all + ability to send mails asynchronously and by batch

Spirit: It should be possible to send mail using directly the JavaMail API and using the helper components defined above or use the MailSender component which acts as a helper but is not as generic.

@Inject MailSenderConfiguration configuration;
@Inject @Named("html") MimeBodyPartFactory htmlPartFactory;
@Inject MimeMessageFactory messageFactory;
@Inject MailSender mailSender;

// Step 1: Create a JavaMail Session
//... with authentication:
Session session = Session.getInstance(configuration.getAllProperties(), new XWikiAuthenticator(configuration));
//... without authentication:
Session session = Session.getInstance(configuration.getAllProperties());

// Step 2: Create the Message to send
MimeMessage message = new MimeMessage(session);
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("[email protected]"));

// Step 3: Add the Message Body
Multipart multipart = new MimeMultipart("mixed");
// Add HTML in the body, with a text alternative and attachments
Map<String, Object> parameters = new HashMap<>();
parameters.put("alternative", "text");
parameters.put("attachments", attachments);
multipart.addBodyPart(htmlPartFactory.create("some html here", parameters));

// Step 4: Send the mail
sender.send(message, session);

Configuration Parameters

  • Introduce new parameters in xwiki.properties:
    mail.sender.host = ...
    mail.sender.port = ...
    mail.sender.username = ...
    mail.sender.password = ...
    mail.sender.from = ...
    mail.sender.properties = ... = ...
    mail.sender.properties = ... = ...
  • Algorithm: first try to find existing parameter names (smtp_server, smtp_port, smtp_from, smtp_server_username, smtp_server_password, javamail_extra_props) in a user, space and wiki level ConfigurationSource and if not found then look for the mail.sender.* property names from a xwikiproperties ConfigurationSource.

Implementation Ideas



Get Connected