Skip to content
Permalink
Browse files Browse the repository at this point in the history
XWIKI-19869: Improve user property storage
  - Provide a new API for sending text based email
  - Provide a migration and a listener for informing users about it
  • Loading branch information
surli committed Jul 8, 2022
1 parent 9c577ba commit 443e839
Show file tree
Hide file tree
Showing 14 changed files with 1,044 additions and 12 deletions.
@@ -0,0 +1,109 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.mail.internal.factory.text;

import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.xwiki.component.annotation.Component;
import org.xwiki.mail.ExtendedMimeMessage;
import org.xwiki.mail.MimeBodyPartFactory;
import org.xwiki.mail.MimeMessageFactory;
import org.xwiki.mail.internal.factory.AbstractMimeMessageFactory;
import org.xwiki.properties.ConverterManager;

/**
* A basic {@link MimeMessageFactory} which is taken a {@link String} as source which represents the content of the
* message.
*
* @version $Id$
* @since 14.6RC1
* @since 14.4.3
* @since 13.10.8
*/
@Component
@Singleton
@Named("text")
public class TextMimeMessageFactory extends AbstractMimeMessageFactory<MimeMessage>
{
@Inject
private ConverterManager converterManager;

@Inject
private MimeBodyPartFactory<String> mimeBodyPartFactory;

@Override
public MimeMessage createMessage(Object source, Map<String, Object> parameters) throws MessagingException
{
// This whole code has been inspired by the implementation of
// org.xwiki.mail.internal.factory.template.AbstractTemplateMimeMessageFactory

// Note: We don't create a Session here ATM since it's not required. The returned MimeMessage will be
// given a valid Session when it's deserialized from the mail content store for sending.
ExtendedMimeMessage message = new ExtendedMimeMessage();

// Handle optional "from" address.
Address from = this.converterManager.convert(Address.class, parameters.get("from"));
if (from != null) {
message.setFrom(from);
}

// Handle optional "to", "cc" and "bcc" addresses.
setRecipient(message, Message.RecipientType.TO, parameters.get("to"));
setRecipient(message, Message.RecipientType.CC, parameters.get("cc"));
setRecipient(message, Message.RecipientType.BCC, parameters.get("bcc"));

// Handle optional "type" parameter to set the mail type
// Set the Message type if passed in parameters
String type = (String) parameters.get("type");
if (type != null) {
message.setType(type);
}

// Handle the subject. Get it from the parameters.
String subject = (String) parameters.get("subject");
message.setSubject(subject);

// Add a default body part taken from the template.
Multipart multipart = new MimeMultipart("mixed");
multipart.addBodyPart(this.mimeBodyPartFactory.create((String) source, parameters));
message.setContent(multipart);

return message;
}

private void setRecipient(MimeMessage message, Message.RecipientType type, Object value)
throws MessagingException
{
Address[] addresses = this.converterManager.convert(Address[].class, value);
if (addresses != null) {
message.setRecipients(type, addresses);
}
}
}
Expand Up @@ -33,3 +33,4 @@ org.xwiki.mail.internal.factory.template.DefaultAttachmentConverter
org.xwiki.mail.internal.factory.files.SerializedFilesMimeMessageFactory
org.xwiki.mail.internal.factory.group.GroupMimeMessageFactory
org.xwiki.mail.internal.factory.usersandgroups.UsersAndGroupsMimeMessageFactory
org.xwiki.mail.internal.factory.text.TextMimeMessageFactory
@@ -0,0 +1,98 @@
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.xwiki.mail.internal.factory.text;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.junit.jupiter.api.Test;
import org.xwiki.mail.ExtendedMimeMessage;
import org.xwiki.mail.MimeBodyPartFactory;
import org.xwiki.properties.ConverterManager;
import org.xwiki.test.junit5.mockito.ComponentTest;
import org.xwiki.test.junit5.mockito.InjectMockComponents;
import org.xwiki.test.junit5.mockito.MockComponent;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* Tests for {@link TextMimeMessageFactory}.
*
* @version $Id$
*/
@ComponentTest
class TextMimeMessageFactoryTest
{
@InjectMockComponents
private TextMimeMessageFactory textMimeMessageFactory;

@MockComponent
private ConverterManager converterManager;

@MockComponent
private MimeBodyPartFactory<String> mimeBodyPartFactory;

@Test
void createMessage() throws MessagingException, IOException
{
String source = "Some mail content";
Map<String, Object> parameters = new HashMap<>();
parameters.put("to", "toto@xwiki.com");
parameters.put("from", "admin@xwiki.com");
parameters.put("type", "text");
parameters.put("subject", "important email");

Address from = new InternetAddress("admin@xwiki.com");
Address to = new InternetAddress("toto@xwiki.com");

when(this.converterManager.convert(Address[].class, "toto@xwiki.com")).thenReturn(new Address[] {to});
when(this.converterManager.convert(Address.class, "admin@xwiki.com")).thenReturn(from);

MimeBodyPart bodyPart = mock(MimeBodyPart.class);
when(this.mimeBodyPartFactory.create(source, parameters)).thenReturn(bodyPart);

ExtendedMimeMessage expectedMessage = new ExtendedMimeMessage();
expectedMessage.setFrom(from);
expectedMessage.setRecipient(Message.RecipientType.TO, to);
expectedMessage.setSubject("important email");
expectedMessage.setType("text");
Multipart multipart = new MimeMultipart("mixed");
multipart.addBodyPart(bodyPart);
expectedMessage.setContent(multipart);

MimeMessage message = this.textMimeMessageFactory.createMessage(source, parameters);
assertEquals(to, message.getRecipients(Message.RecipientType.TO)[0]);
assertEquals(from, message.getFrom()[0]);
assertEquals("important email", message.getSubject());
assertEquals(bodyPart, ((Multipart) message.getContent()).getBodyPart(0));
}
}

0 comments on commit 443e839

Please sign in to comment.