JAMES-2557 Use Mail::getMaybeSender everywhere

    Note that dificulty arised when trying to send a mail without sender using 
the MailetContext.

    The retained solution is to pass a mail with the right target processor 
specified.


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/8ce35148
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/8ce35148
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/8ce35148

Branch: refs/heads/master
Commit: 8ce351489a6ade4411170307cb6db0bba638e209
Parents: df43357
Author: Benoit Tellier <[email protected]>
Authored: Thu Oct 25 13:56:09 2018 +0700
Committer: Benoit Tellier <[email protected]>
Committed: Tue Oct 30 09:39:08 2018 +0700

----------------------------------------------------------------------
 .../custom/mailets/SendPromotionCode.java       |  2 +-
 .../james/ai/classic/BayesianAnalysis.java      | 12 +++---
 .../base/AutomaticallySentMailDetectorImpl.java | 22 +++++------
 .../james/transport/mailets/AbstractSign.java   | 18 ++++-----
 .../james/transport/mailets/SMIMESign.java      |  2 +-
 .../apache/james/transport/mailets/Sign.java    |  2 +-
 .../transport/mailets/ICALToJsonAttribute.java  |  2 +-
 .../james/transport/mailets/ClamAVScan.java     |  2 +-
 .../transport/mailets/ContactExtractor.java     |  5 +--
 .../james/transport/mailets/ServerTime.java     |  6 ++-
 .../matchers/AbstractQuotaMatcher.java          | 19 ++++++----
 .../james/transport/matchers/RecipientIs.java   |  5 ++-
 .../james/transport/matchers/SenderHostIs.java  |  9 ++---
 .../transport/matchers/SenderHostIsLocal.java   | 11 +++---
 .../james/transport/matchers/SenderIs.java      |  7 ++--
 .../james/transport/matchers/SenderIsLocal.java | 10 ++---
 .../james/transport/matchers/SenderIsNull.java  | 12 ++----
 .../james/transport/matchers/SenderIsRegex.java |  6 +--
 .../utils/MailAddressCollectionReader.java      |  9 +++--
 .../james/transport/matchers/SenderIsTest.java  |  5 ++-
 .../util/MailAddressCollectionReaderTest.java   | 16 ++++----
 .../org/apache/mailet/base/test/FakeMail.java   | 15 --------
 .../mailet/base/test/FakeMailContext.java       |  7 +++-
 .../org/apache/james/server/core/MailImpl.java  | 15 +++++++-
 .../apache/james/server/core/MailImplTest.java  |  5 ++-
 .../org/apache/james/util/OptionalUtils.java    | 13 +++++++
 .../mailrepository/jcr/JCRMailRepository.java   |  7 ++--
 .../mailrepository/jdbc/JDBCMailRepository.java |  8 ++--
 .../impl/JamesMailetContext.java                | 15 +++++---
 .../impl/camel/CamelProcessor.java              |  2 +-
 .../impl/camel/MatcherSplitter.java             |  2 +-
 .../transport/mailets/BayesianAnalysis.java     | 17 +++++----
 .../apache/james/transport/mailets/Bounce.java  |  4 +-
 .../james/transport/mailets/DSNBounce.java      | 13 ++++---
 .../mailets/RecipientRewriteTableProcessor.java | 26 ++++++++++---
 .../james/transport/mailets/RemoteDelivery.java |  2 +-
 .../org/apache/james/transport/mailets/SPF.java |  9 +----
 .../mailets/ToSenderDomainRepository.java       | 10 ++++-
 .../james/transport/mailets/ToSenderFolder.java | 10 +++--
 .../transport/mailets/WhiteListManager.java     | 12 +++---
 .../mailets/delivery/DeliveryUtils.java         | 34 -----------------
 .../mailets/delivery/MailDispatcher.java        | 23 +++++++----
 .../mailets/delivery/SimpleMailStore.java       |  6 +--
 .../mailets/jsieve/RedirectAction.java          |  1 +
 .../mailets/jsieve/SieveMailAdapter.java        |  3 +-
 .../transport/mailets/jsieve/VacationReply.java | 16 ++++----
 .../mailets/managesieve/ManageSieveMailet.java  | 12 +++---
 .../mailets/redirect/NotifyMailetsMessage.java  |  2 +-
 .../mailets/redirect/ProcessRedirectNotify.java |  8 ++--
 .../mailets/remote/delivery/Bouncer.java        |  2 +-
 .../mailets/remote/delivery/MailDelivrer.java   |  2 +-
 .../remote/delivery/MailDelivrerToHost.java     |  7 +---
 .../matchers/AbstractSQLWhitelistMatcher.java   |  4 +-
 .../james/transport/matchers/IsInWhiteList.java |  5 ++-
 .../transport/matchers/IsSenderInRRTLoop.java   |  4 +-
 .../transport/matchers/SenderInFakeDomain.java  |  4 +-
 .../james/transport/matchers/dlp/Dlp.java       |  5 +--
 .../transport/matchers/dlp/DlpDomainRules.java  |  4 +-
 .../james/transport/util/ReplyToUtils.java      |  6 +--
 .../transport/util/SpecialAddressesUtils.java   | 20 +++-------
 .../james/samples/mailets/HelloWorldMailet.java |  9 ++---
 .../samples/mailets/InstrumentationMailet.java  |  4 +-
 .../RecipientRewriteTableProcessorTest.java     | 20 +++++-----
 .../mailets/delivery/DeliveryUtilsTest.java     | 40 --------------------
 .../mailrepository/MailRepositoryContract.java  |  3 +-
 .../CassandraMailRepositoryMailDAO.java         |  4 +-
 .../CassandraMailRepositoryMailDAOTest.java     |  2 +-
 .../james/fetchmail/MessageProcessor.java       |  2 +-
 .../james/jmap/mailet/VacationMailet.java       |  9 +++--
 .../apache/james/jmap/mailet/VacationReply.java |  8 ++--
 .../methods/SetMessagesUpdateProcessor.java     |  9 +++--
 .../apache/james/jmap/send/MailFactoryTest.java |  3 +-
 .../james/smtpserver/SendMailHandler.java       |  2 +-
 .../apache/james/smtpserver/SMTPServerTest.java |  2 +-
 .../james/webadmin/dto/MailQueueItemDTO.java    | 10 +++--
 .../webadmin/dto/MailQueueItemDTOTest.java      |  2 +-
 .../webadmin/routes/MailQueueRoutesTest.java    |  3 +-
 .../org/apache/james/webadmin/dto/MailDto.java  |  2 +-
 .../james/queue/api/MailQueueContract.java      | 25 +++++++++---
 .../apache/james/queue/jms/JMSMailQueue.java    |  2 +-
 .../queue/library/MailQueueManagement.java      |  6 +--
 .../queue/memory/MemoryMailQueueFactory.java    |  2 +-
 .../james/queue/rabbitmq/MailReferenceDTO.java  |  2 +-
 .../rabbitmq/view/api/DeleteCondition.java      |  4 +-
 .../view/cassandra/EnqueuedMailsDAO.java        |  6 +--
 .../apache/james/utils/SMTPMessageSender.java   |  2 +-
 86 files changed, 350 insertions(+), 375 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/examples/custom-mailets/src/main/java/org/apache/james/examples/custom/mailets/SendPromotionCode.java
----------------------------------------------------------------------
diff --git 
a/examples/custom-mailets/src/main/java/org/apache/james/examples/custom/mailets/SendPromotionCode.java
 
b/examples/custom-mailets/src/main/java/org/apache/james/examples/custom/mailets/SendPromotionCode.java
index 898b7cd..4ad2b07 100644
--- 
a/examples/custom-mailets/src/main/java/org/apache/james/examples/custom/mailets/SendPromotionCode.java
+++ 
b/examples/custom-mailets/src/main/java/org/apache/james/examples/custom/mailets/SendPromotionCode.java
@@ -45,7 +45,7 @@ public class SendPromotionCode extends GenericMailet {
             "Here is the following promotion code that you can use on your 
next order: " + promotionCode);
 
         MailAddress sender = getMailetContext().getPostmaster();
-        ImmutableList<MailAddress> recipients = 
ImmutableList.of(mail.getSender());
+        ImmutableList<MailAddress> recipients = mail.getMaybeSender().asList();
 
         getMailetContext()
             .sendMail(sender, recipients, response);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/ai/src/main/java/org/apache/james/ai/classic/BayesianAnalysis.java
----------------------------------------------------------------------
diff --git 
a/mailet/ai/src/main/java/org/apache/james/ai/classic/BayesianAnalysis.java 
b/mailet/ai/src/main/java/org/apache/james/ai/classic/BayesianAnalysis.java
index c4be663..a91d178 100644
--- a/mailet/ai/src/main/java/org/apache/james/ai/classic/BayesianAnalysis.java
+++ b/mailet/ai/src/main/java/org/apache/james/ai/classic/BayesianAnalysis.java
@@ -316,12 +316,7 @@ public class BayesianAnalysis extends GenericMailet {
             probabilityForm.applyPattern("##0.##%");
             String probabilityString = probabilityForm.format(probability);
 
-            String senderString;
-            if (mail.getSender() == null) {
-                senderString = "null";
-            } else {
-                senderString = mail.getSender().toString();
-            }
+            String senderString = mail.getMaybeSender().asString("null");
             if (probability > 0.1) {
                 final Collection<MailAddress> recipients = 
mail.getRecipients();
                 if (LOGGER.isDebugEnabled()) {
@@ -343,7 +338,10 @@ public class BayesianAnalysis extends GenericMailet {
     }
 
     private boolean isSenderLocal(Mail mail) {
-        return mail.getSender() != null && 
getMailetContext().isLocalServer(mail.getSender().getDomain());
+        return mail.getMaybeSender().asOptional()
+            .map(MailAddress::getDomain)
+            .map(domain -> getMailetContext().isLocalServer(domain))
+            .orElse(false);
     }
 
     void loadData(Connection conn) throws java.sql.SQLException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
----------------------------------------------------------------------
diff --git 
a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
 
b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
index 43645a3..f7cb0af 100644
--- 
a/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
+++ 
b/mailet/base/src/main/java/org/apache/mailet/base/AutomaticallySentMailDetectorImpl.java
@@ -48,7 +48,7 @@ public class AutomaticallySentMailDetectorImpl implements 
AutomaticallySentMailD
 
     @Override
     public boolean isAutomaticallySent(Mail mail) throws MessagingException {
-        return mail.getSender() == null ||
+        return !mail.hasSender() ||
             isMailingList(mail) ||
             isAutoSubmitted(mail) ||
             isMdnSentAutomatically(mail);
@@ -61,17 +61,15 @@ public class AutomaticallySentMailDetectorImpl implements 
AutomaticallySentMailD
     }
 
     private boolean senderIsMailingList(Mail mail) {
-        MailAddress sender = mail.getSender();
-        if (sender == null) {
-            return false;
-        }
-
-        String localPart = sender.getLocalPart();
-        return localPart.startsWith("owner-")
-            || localPart.endsWith("-request")
-            || localPart.equalsIgnoreCase("MAILER-DAEMON")
-            || localPart.equalsIgnoreCase("LISTSERV")
-            || localPart.equalsIgnoreCase("majordomo");
+        return mail.getMaybeSender()
+            .asOptional()
+            .map(MailAddress::getLocalPart)
+            .map(localPart ->  localPart.startsWith("owner-")
+                || localPart.endsWith("-request")
+                || localPart.equalsIgnoreCase("MAILER-DAEMON")
+                || localPart.equalsIgnoreCase("LISTSERV")
+                || localPart.equalsIgnoreCase("majordomo"))
+            .orElse(false);
     }
 
     private boolean headerIsMailingList(Mail mail) throws MessagingException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/crypto/src/main/java/org/apache/james/transport/mailets/AbstractSign.java
----------------------------------------------------------------------
diff --git 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/AbstractSign.java
 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/AbstractSign.java
index a1cbb19..461250d 100644
--- 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/AbstractSign.java
+++ 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/AbstractSign.java
@@ -495,7 +495,7 @@ public abstract class AbstractSign extends GenericMailet {
   
             if (isRebuildFrom()) {
                 // builds a new "mixed" "From:" header
-                InternetAddress modifiedFromIA = new 
InternetAddress(getKeyHolder().getSignerAddress(), mail.getSender().toString());
+                InternetAddress modifiedFromIA = new 
InternetAddress(getKeyHolder().getSignerAddress(), 
mail.getMaybeSender().asString());
                 newMessage.setFrom(modifiedFromIA);
                 
                 // if the original "ReplyTo:" header is missing sets it to the 
original "From:" header
@@ -521,7 +521,7 @@ public abstract class AbstractSign extends GenericMailet {
             mail.setAttribute(SMIMEAttributeNames.SMIME_SIGNER_ADDRESS, 
getKeyHolder().getSignerAddress());
             
             if (isDebug()) {
-                LOGGER.debug("Message signed, reverse-path: {}, Id: {}", 
mail.getSender(), messageId);
+                LOGGER.debug("Message signed, reverse-path: {}, Id: {}", 
mail.getMaybeSender().asString(), messageId);
             }
             
         } catch (MessagingException me) {
@@ -554,19 +554,18 @@ public abstract class AbstractSign extends GenericMailet {
      * @return True if can be signed.
      */
     protected boolean isOkToSign(Mail mail) throws MessagingException {
-
-        MailAddress reversePath = mail.getSender();
-        
         // Is it a bounce?
-        if (reversePath == null) {
+        if (!mail.hasSender()) {
             LOGGER.info("Can not sign: no sender");
             return false;
         }
+
+        MailAddress reversePath = mail.getMaybeSender().get();
         
         String authUser = (String) 
mail.getAttribute(Mail.SMTP_AUTH_USER_ATTRIBUTE_NAME);
         // was the sender user SMTP authorized?
         if (authUser == null) {
-            LOGGER.info("Can not sign mail for sender <{}> as he is not a SMTP 
authenticated user", mail.getSender());
+            LOGGER.info("Can not sign mail for sender <{}> as he is not a SMTP 
authenticated user", mail.getMaybeSender().asString());
             return false;
         }
         
@@ -627,11 +626,10 @@ public abstract class AbstractSign extends GenericMailet {
      */    
     protected final boolean fromAddressSameAsReverse(Mail mail) {
         
-        MailAddress reversePath = mail.getSender();
-        
-        if (reversePath == null) {
+        if (!mail.hasSender()) {
             return false;
         }
+        MailAddress reversePath = mail.getMaybeSender().get();
         
         try {
             InternetAddress[] fromArray = (InternetAddress[]) 
mail.getMessage().getFrom();

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMESign.java
----------------------------------------------------------------------
diff --git 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMESign.java 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMESign.java
index dad9cb9..e2f0821 100644
--- 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMESign.java
+++ 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/SMIMESign.java
@@ -202,7 +202,7 @@ public class SMIMESign extends Sign {
             
signatureReason.setText(getReplacedExplanationText(getExplanationText(),
                                                                getSignerName(),
                                                                
getKeyHolder().getSignerAddress(),
-                                                               
mail.getSender().toString(),
+                                                               
mail.getMaybeSender().asString(),
                                                                headers));
             
             signatureReason.setFileName("SignatureExplanation.txt");

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/crypto/src/main/java/org/apache/james/transport/mailets/Sign.java
----------------------------------------------------------------------
diff --git 
a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/Sign.java 
b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/Sign.java
index ecf8cd0..16dec08 100644
--- a/mailet/crypto/src/main/java/org/apache/james/transport/mailets/Sign.java
+++ b/mailet/crypto/src/main/java/org/apache/james/transport/mailets/Sign.java
@@ -192,7 +192,7 @@ public class Sign extends AbstractSign {
             
signatureReason.setText(getReplacedExplanationText(getExplanationText(),
                                                                getSignerName(),
                                                                
getKeyHolder().getSignerAddress(),
-                                                               
mail.getSender().toString(),
+                                                               
mail.getMaybeSender().asString(),
                                                                headers));
             
             signatureReason.setFileName("SignatureExplanation.txt");

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
----------------------------------------------------------------------
diff --git 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
index 5b95106..f1605bb 100644
--- 
a/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
+++ 
b/mailet/icalendar/src/main/java/org/apache/james/transport/mailets/ICALToJsonAttribute.java
@@ -220,7 +220,7 @@ public class ICALToJsonAttribute extends GenericMailet {
             .map(address -> (InternetAddress) address)
             .map(InternetAddress::getAddress)
             .findFirst();
-        Optional<String> fromEnvelope = Optional.ofNullable(mail.getSender())
+        Optional<String> fromEnvelope = mail.getMaybeSender().asOptional()
             .map(MailAddress::asString);
 
         return OptionalUtils.or(

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/mailets/ClamAVScan.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ClamAVScan.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ClamAVScan.java
index 9233b21..79c6e53 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ClamAVScan.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ClamAVScan.java
@@ -821,7 +821,7 @@ public class ClamAVScan extends GenericMailet {
             PrintWriter out = new PrintWriter(sout, true);
 
             out.print("Mail details:");
-            out.print(" MAIL FROM: " + mail.getSender());
+            out.print(" MAIL FROM: " + mail.getMaybeSender().asString());
             Iterator<MailAddress> rcptTo = mail.getRecipients().iterator();
             out.print(", RCPT TO: " + rcptTo.next());
             while (rcptTo.hasNext()) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java
index f52bbab..64e0524 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java
@@ -18,7 +18,6 @@
  ****************************************************************/
 package org.apache.james.transport.mailets;
 
-import java.io.IOException;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Stream;
@@ -101,11 +100,11 @@ public class ContactExtractor extends GenericMailet 
implements Mailet {
     }
 
     @VisibleForTesting
-    Optional<String> extractContacts(Mail mail) throws MessagingException, 
IOException {
+    Optional<String> extractContacts(Mail mail) throws MessagingException {
         ImmutableList<String> allRecipients = 
getAllRecipients(mail.getMessage());
 
         if (hasRecipient(allRecipients)) {
-            return Optional.of(mail.getSender())
+            return mail.getMaybeSender().asOptional()
                 .map(MailAddress::asString)
                 .map(sender -> new ExtractedContacts(sender, allRecipients))
                 .map(Throwing.function(extractedContacts -> 
objectMapper.writeValueAsString(extractedContacts)));

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/mailets/ServerTime.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ServerTime.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ServerTime.java
index bf7ed37..7dc52d3 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ServerTime.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ServerTime.java
@@ -46,6 +46,10 @@ public class ServerTime extends GenericMailet {
      */
     @Override
     public void service(Mail mail) throws javax.mail.MessagingException {
+        if (!mail.hasSender()) {
+            return;
+        }
+
         MimeMessage response = (MimeMessage)mail.getMessage().reply(false);
         response.setSubject("The time is now...");
         String textBuffer = "This mail server thinks it's " + (new 
java.util.Date()).toString() + ".";
@@ -61,7 +65,7 @@ public class ServerTime extends GenericMailet {
         }
 
         if (response.getAllRecipients() == null) {
-            response.setRecipients(MimeMessage.RecipientType.TO, 
mail.getSender().toString());
+            response.setRecipients(MimeMessage.RecipientType.TO, 
mail.getMaybeSender().get().toString());
         }
 
         response.saveChanges();

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/AbstractQuotaMatcher.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AbstractQuotaMatcher.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AbstractQuotaMatcher.java
index e097e8e..219fadd 100755
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AbstractQuotaMatcher.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AbstractQuotaMatcher.java
@@ -17,8 +17,6 @@
  * under the License.                                           *
  ****************************************************************/
 
-
-
 package org.apache.james.transport.matchers;
 
 import java.util.ArrayList;
@@ -27,6 +25,7 @@ import java.util.Collection;
 import javax.mail.MessagingException;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.mailet.Experimental;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMatcher;
@@ -57,7 +56,7 @@ public abstract class AbstractQuotaMatcher extends 
GenericMatcher {
     @Override
     public final Collection<MailAddress> match(Mail mail) throws 
MessagingException {
         Collection<MailAddress> matching = null;
-        if (isSenderChecked(mail.getSender())) {
+        if (isSenderChecked(mail.getMaybeSender())) {
             matching = new ArrayList<>();
             for (MailAddress recipient : mail.getRecipients()) {
                 if (isRecipientChecked(recipient) && isOverQuota(recipient, 
mail)) {
@@ -97,9 +96,15 @@ public abstract class AbstractQuotaMatcher extends 
GenericMatcher {
      * to its check.
      *
      * @param sender the sender to check
-     */    
-    protected boolean isSenderChecked(MailAddress sender) throws 
MessagingException {
-        return !(sender == null || 
getMailetContext().getPostmaster().equals(sender));
+     */
+    private boolean isSenderChecked(MaybeSender sender) {
+        return sender.asOptional()
+            .filter(mailAddress -> !isPostmaster(mailAddress))
+            .isPresent();
+    }
+
+    private boolean isPostmaster(MailAddress mailAddress) {
+        return getMailetContext().getPostmaster().equals(mailAddress);
     }
 
     /** 
@@ -111,7 +116,7 @@ public abstract class AbstractQuotaMatcher extends 
GenericMatcher {
      * @param recipient the recipient to check
      */    
     protected boolean isRecipientChecked(MailAddress recipient) throws 
MessagingException {
-        return !(getMailetContext().getPostmaster().equals(recipient));
+        return !(isPostmaster(recipient));
     }
 
     /** 

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIs.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIs.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIs.java
index 5d53105..69a4b44 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIs.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIs.java
@@ -20,6 +20,7 @@
 package org.apache.james.transport.matchers;
 
 import java.util.Collection;
+import java.util.Optional;
 
 import javax.mail.MessagingException;
 
@@ -43,7 +44,7 @@ import com.google.common.base.Strings;
  */
 public class RecipientIs extends GenericRecipientMatcher {
 
-    private Collection<MailAddress> recipients;
+    private Collection<Optional<MailAddress>> recipients;
 
     @Override
     public void init() throws javax.mail.MessagingException {
@@ -58,6 +59,6 @@ public class RecipientIs extends GenericRecipientMatcher {
 
     @Override
     public boolean matchRecipient(MailAddress recipient) {
-        return recipients.contains(recipient);
+        return recipients.contains(Optional.of(recipient));
     }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIs.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIs.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIs.java
index c9caffb..48eaf0f 100755
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIs.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIs.java
@@ -78,7 +78,9 @@ public class SenderHostIs extends GenericMatcher {
     @Override
     public Collection<MailAddress> match(Mail mail) {
         try {
-            if (hasSender(mail) && 
senderHosts.contains(mail.getSender().getDomain())) {
+            if (mail.getMaybeSender().asOptional()
+                    .map(mailAddress -> 
senderHosts.contains(mailAddress.getDomain()))
+                    .orElse(false)) {
                 return mail.getRecipients();
             }
         } catch (Exception e) {
@@ -87,9 +89,4 @@ public class SenderHostIs extends GenericMatcher {
 
         return null;    //No match.
     }
-
-    private boolean hasSender(Mail mail) {
-        return mail.getSender() != null
-            && !mail.getSender().isNullSender();
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIsLocal.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIsLocal.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIsLocal.java
index a248c08..996f2d0 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIsLocal.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderHostIsLocal.java
@@ -39,18 +39,17 @@ import org.apache.mailet.base.GenericMatcher;
 public class SenderHostIsLocal extends GenericMatcher {
     @Override
     public Collection<MailAddress> match(Mail mail) {
-        if (mail.getSender() != null && isLocalServer(mail)) {
+        if (mail.getMaybeSender().asOptional()
+                .map(this::isLocalServer)
+                .orElse(false)) {
             return mail.getRecipients();
         }
         return null;
         
     }
 
-    private boolean isLocalServer(Mail mail) {
-        if (mail.getSender().isNullSender()) {
-            return false;
-        }
-        return 
this.getMailetContext().isLocalServer(mail.getSender().getDomain());
+    private boolean isLocalServer(MailAddress sender) {
+        return this.getMailetContext().isLocalServer(sender.getDomain());
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIs.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIs.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIs.java
index 821692d..0d42e42 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIs.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIs.java
@@ -47,10 +47,10 @@ import com.google.common.base.Strings;
  */
 public class SenderIs extends GenericMatcher {
 
-    private Set<MailAddress> senders;
+    private Set<Optional<MailAddress>> senders;
 
     @VisibleForTesting
-    Set<MailAddress> getSenders() {
+    Set<Optional<MailAddress>> getSenders() {
         return senders;
     }
 
@@ -67,8 +67,7 @@ public class SenderIs extends GenericMatcher {
 
     @Override
     public Collection<MailAddress> match(Mail mail) {
-        MailAddress sanitizedSender = 
Optional.ofNullable(mail.getSender()).orElse(MailAddress.nullSender());
-        if (senders.contains(sanitizedSender)) {
+        if (senders.contains(mail.getMaybeSender().asOptional())) {
             return mail.getRecipients();
         } else {
             return null;

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsLocal.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsLocal.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsLocal.java
index 925c596..fcd388b 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsLocal.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsLocal.java
@@ -19,7 +19,6 @@
 package org.apache.james.transport.matchers;
 
 import java.util.Collection;
-import java.util.Optional;
 
 import org.apache.james.core.MailAddress;
 import org.apache.mailet.Mail;
@@ -32,17 +31,16 @@ public class SenderIsLocal extends GenericMatcher {
 
     @Override
     public final Collection<MailAddress> match(Mail mail) {
-        if (isLocal(mail.getSender())) {
+        if (mail.getMaybeSender().asOptional()
+                .map(this::isLocal)
+                .orElse(false)) {
             return mail.getRecipients();
         }
         return null;
     }
 
     private boolean isLocal(MailAddress mailAddress) {
-        return Optional.ofNullable(mailAddress)
-            .filter(address -> !address.isNullSender())
-            .map(address -> getMailetContext().isLocalEmail(address))
-            .orElse(false);
+        return getMailetContext().isLocalEmail(mailAddress);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsNull.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsNull.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsNull.java
index 6fba3c2..1b48fda 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsNull.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsNull.java
@@ -35,18 +35,12 @@ import org.apache.mailet.base.GenericMatcher;
  * @since 2.2.0
  */
 public class SenderIsNull extends GenericMatcher {
-
     @Override
     public Collection<MailAddress> match(Mail mail) {
-        if (isNullSender(mail)) {
-            return mail.getRecipients();
-        } else {
+        if (mail.hasSender()) {
             return null;
+        } else {
+            return mail.getRecipients();
         }
     }
-
-    private boolean isNullSender(Mail mail) {
-        return mail.getSender() == null
-            || mail.getSender().isNullSender();
-    }
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsRegex.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsRegex.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsRegex.java
index a72272f..ef308d5 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsRegex.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/SenderIsRegex.java
@@ -74,11 +74,7 @@ public class SenderIsRegex extends GenericMatcher {
 
     @Override
     public Collection<MailAddress> match(Mail mail) {
-        MailAddress mailAddress = mail.getSender();
-        if (mailAddress == null) {
-            return null;
-        }
-        String senderString = mailAddress.asString();
+        String senderString = mail.getMaybeSender().asString();
         if (pattern.matcher(senderString).matches()) {
             return mail.getRecipients();
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MailAddressCollectionReader.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MailAddressCollectionReader.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MailAddressCollectionReader.java
index e0ea2fd..733d4dc 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MailAddressCollectionReader.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/utils/MailAddressCollectionReader.java
@@ -19,6 +19,7 @@
 
 package org.apache.james.transport.matchers.utils;
 
+import java.util.Optional;
 import java.util.Set;
 
 import javax.mail.internet.AddressException;
@@ -33,7 +34,7 @@ import com.google.common.base.Strings;
 
 public class MailAddressCollectionReader {
 
-    public static Set<MailAddress> read(String condition) {
+    public static Set<Optional<MailAddress>> read(String condition) {
         Preconditions.checkArgument(!Strings.isNullOrEmpty(condition));
         return Splitter.onPattern("(,| |\t)").splitToList(condition)
             .stream()
@@ -42,12 +43,12 @@ public class MailAddressCollectionReader {
             .collect(Guavate.toImmutableSet());
     }
 
-    private static MailAddress getMailAddress(String s) {
+    private static Optional<MailAddress> getMailAddress(String s) {
         try {
             if (s.equals(MailAddress.NULL_SENDER_AS_STRING)) {
-                return MailAddress.nullSender();
+                return Optional.empty();
             }
-            return new MailAddress(s);
+            return Optional.of(new MailAddress(s));
         } catch (AddressException e) {
             throw new RuntimeException(e);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/test/java/org/apache/james/transport/matchers/SenderIsTest.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/SenderIsTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/SenderIsTest.java
index ac9ae53..385bd68 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/SenderIsTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/SenderIsTest.java
@@ -23,6 +23,8 @@ package org.apache.james.transport.matchers;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import java.util.Optional;
+
 import javax.mail.MessagingException;
 
 import org.apache.james.core.MailAddress;
@@ -154,7 +156,8 @@ class SenderIsTest {
                 .condition(mailAddress + ", " + SENDER_NAME)
                 .build());
 
-        assertThat(matcher.getSenders()).containsExactly(new 
MailAddress(mailAddress), new MailAddress(SENDER_NAME));
+        assertThat(matcher.getSenders()).containsExactly(Optional.of(new 
MailAddress(mailAddress)),
+            Optional.of(new MailAddress(SENDER_NAME)));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/standard/src/test/java/org/apache/james/transport/matchers/util/MailAddressCollectionReaderTest.java
----------------------------------------------------------------------
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/util/MailAddressCollectionReaderTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/util/MailAddressCollectionReaderTest.java
index 6bad784..e75aa2e 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/util/MailAddressCollectionReaderTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/util/MailAddressCollectionReaderTest.java
@@ -22,6 +22,8 @@ package org.apache.james.transport.matchers.util;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
+import java.util.Optional;
+
 import org.apache.james.core.MailAddress;
 import org.apache.james.transport.matchers.utils.MailAddressCollectionReader;
 import org.junit.jupiter.api.Test;
@@ -57,13 +59,13 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress.toString()))
-            .containsExactly(mailAddress);
+            .containsExactly(Optional.of(mailAddress));
     }
 
     @Test
     void readShouldParseNullSender() {
         assertThat(MailAddressCollectionReader.read("<>"))
-            .containsExactly(MailAddress.nullSender());
+            .containsExactly(Optional.empty());
     }
 
     @Test
@@ -72,7 +74,7 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress2 = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress1.toString() + 
"," + mailAddress2.toString()))
-            .containsExactly(mailAddress1, mailAddress2);
+            .containsExactly(Optional.of(mailAddress1), 
Optional.of(mailAddress2));
     }
 
     @Test
@@ -81,7 +83,7 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress2 = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress1.toString() + 
" " + mailAddress2.toString()))
-            .containsExactly(mailAddress1, mailAddress2);
+            .containsExactly(Optional.of(mailAddress1), 
Optional.of(mailAddress2));
     }
 
     @Test
@@ -90,7 +92,7 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress2 = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress1.toString() + 
"\t" + mailAddress2.toString()))
-            .containsExactly(mailAddress1, mailAddress2);
+            .containsExactly(Optional.of(mailAddress1), 
Optional.of(mailAddress2));
     }
 
 
@@ -100,7 +102,7 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress2 = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress1.toString() + 
",\t  \t,\t \t " + mailAddress2.toString()))
-            .containsExactly(mailAddress1, mailAddress2);
+            .containsExactly(Optional.of(mailAddress1), 
Optional.of(mailAddress2));
     }
 
     @Test
@@ -108,7 +110,7 @@ class MailAddressCollectionReaderTest {
         MailAddress mailAddress = new MailAddress("[email protected]");
 
         assertThat(MailAddressCollectionReader.read(mailAddress.toString() + 
", " + mailAddress.toString()))
-            .containsExactly(mailAddress);
+            .containsExactly(Optional.of(mailAddress));
     }
 
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
index 6791a1f..895256e 100644
--- a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMail.java
@@ -72,21 +72,6 @@ public class FakeMail implements Mail, Serializable {
                 .build();
     }
 
-    public static FakeMail fromMail(Mail mail) throws MessagingException {
-        return new FakeMail(mail.getMessage(),
-            Lists.newArrayList(mail.getRecipients()),
-            mail.getName(),
-            mail.getSender(),
-            mail.getState(),
-            mail.getErrorMessage(),
-            mail.getLastUpdated(),
-            attributes(mail),
-            mail.getMessageSize(),
-            mail.getRemoteAddr(),
-            mail.getRemoteHost(),
-            mail.getPerRecipientSpecificHeaders());
-    }
-
     public static FakeMail from(MimeMessage message) throws MessagingException 
{
         return builder()
                 .mimeMessage(message)

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
----------------------------------------------------------------------
diff --git 
a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java 
b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
index 8dbf7f9..7fbb014 100644
--- a/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
+++ b/mailet/test/src/main/java/org/apache/mailet/base/test/FakeMailContext.java
@@ -64,7 +64,7 @@ public class FakeMailContext implements MailetContext {
 
     public static SentMail.Builder fromMail(Mail mail) throws 
MessagingException {
         return sentMailBuilder()
-            .sender(mail.getSender())
+            .sender(mail.getMaybeSender().asOptional())
             .recipients(mail.getRecipients())
             .message(mail.getMessage())
             .state(mail.getState())
@@ -133,6 +133,11 @@ public class FakeMailContext implements MailetContext {
                 return this;
             }
 
+            public Builder sender(Optional<MailAddress> sender) {
+                sender.ifPresent(this::sender);
+                return this;
+            }
+
             public Builder sender(String sender) throws AddressException {
                 return sender(new MailAddress(sender));
             }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
 
b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
index af13b67..ae9c853 100644
--- 
a/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
+++ 
b/server/container/core/src/main/java/org/apache/james/server/core/MailImpl.java
@@ -47,6 +47,7 @@ import javax.mail.internet.ParseException;
 
 import org.apache.commons.lang.RandomStringUtils;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.lifecycle.api.Disposable;
 import org.apache.james.lifecycle.api.LifecycleUtil;
@@ -176,7 +177,17 @@ public class MailImpl implements Disposable, Mail {
         }
 
         public Builder sender(MailAddress sender) {
-            this.sender = Optional.ofNullable(sender);
+            return sender(Optional.ofNullable(sender));
+        }
+
+        public Builder sender(Optional<MailAddress> sender) {
+            this.sender = sender;
+            return this;
+        }
+
+
+        public Builder sender(MaybeSender sender) {
+            this.sender = sender.asOptional();
             return this;
         }
 
@@ -387,7 +398,7 @@ public class MailImpl implements Disposable, Mail {
         }
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "deprecated"})
     private MailImpl(Mail mail, String newName) throws MessagingException {
         this(newName, mail.getSender(), mail.getRecipients(), 
mail.getMessage());
         setRemoteHost(mail.getRemoteHost());

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java
----------------------------------------------------------------------
diff --git 
a/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java
 
b/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java
index 06d9e16..62d2f1e 100644
--- 
a/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java
+++ 
b/server/container/core/src/test/java/org/apache/james/server/core/MailImplTest.java
@@ -31,6 +31,7 @@ import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.MailAddressFixture;
@@ -64,7 +65,7 @@ public class MailImplTest {
         assertThat(mail.getRemoteHost()).describedAs("initial remote host is 
localhost").isEqualTo("localhost");
         assertThat(mail.getState()).describedAs("default initial 
state").isEqualTo(Mail.DEFAULT);
         assertThat(mail.getMessage()).isNull();
-        assertThat(mail.getSender()).isNull();
+        assertThat(mail.getMaybeSender()).isEqualTo(MaybeSender.nullSender());
         assertThat(mail.getName()).isNull();
     }
 
@@ -97,7 +98,7 @@ public class MailImplTest {
         MailAddress senderMailAddress = new MailAddress(sender);
         MailImpl mail = new MailImpl(name, senderMailAddress, recipients);
 
-        assertThat(mail.getSender().asString()).isEqualTo(sender);
+        assertThat(mail.getMaybeSender().get().asString()).isEqualTo(sender);
         assertThat(mail.getName()).isEqualTo(name);
 
      }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/container/util/src/main/java/org/apache/james/util/OptionalUtils.java
----------------------------------------------------------------------
diff --git 
a/server/container/util/src/main/java/org/apache/james/util/OptionalUtils.java 
b/server/container/util/src/main/java/org/apache/james/util/OptionalUtils.java
index 4a3449c..4d458cd 100644
--- 
a/server/container/util/src/main/java/org/apache/james/util/OptionalUtils.java
+++ 
b/server/container/util/src/main/java/org/apache/james/util/OptionalUtils.java
@@ -23,6 +23,9 @@ import java.util.Optional;
 import java.util.function.Supplier;
 import java.util.stream.Stream;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+
 public class OptionalUtils {
 
     @FunctionalInterface
@@ -42,6 +45,16 @@ public class OptionalUtils {
             .orElse(Stream.of());
     }
 
+    public static <T> ImmutableList<T> toList(Optional<T> optional) {
+        return optional.map(ImmutableList::of)
+            .orElse(ImmutableList.of());
+    }
+
+    public static <T> ImmutableSet<T> toSet(Optional<T> optional) {
+        return optional.map(ImmutableSet::of)
+            .orElse(ImmutableSet.of());
+    }
+
     @SafeVarargs
     public static <T> Optional<T> or(Optional<T>... optionals) {
         return orStream(Arrays.stream(optionals));

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
----------------------------------------------------------------------
diff --git 
a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
 
b/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
index c2f8218..a546847 100644
--- 
a/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
+++ 
b/server/data/data-jcr/src/main/java/org/apache/james/mailrepository/jcr/JCRMailRepository.java
@@ -58,6 +58,7 @@ import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.util.ISO9075;
 import org.apache.jackrabbit.util.Text;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.mailrepository.api.MailKey;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.lib.AbstractMailRepository;
@@ -210,7 +211,7 @@ public class JCRMailRepository extends 
AbstractMailRepository implements MailRep
         setError(node, mail.getErrorMessage());
         setRemoteHost(node, mail.getRemoteHost());
         setRemoteAddr(node, mail.getRemoteAddr());
-        setSender(node, mail.getSender());
+        setSender(node, mail.getMaybeSender());
         setRecipients(node, mail.getRecipients());
         setMessage(node, mail.getMessage());
         setAttributes(node, mail);
@@ -417,8 +418,8 @@ public class JCRMailRepository extends 
AbstractMailRepository implements MailRep
      * @throws RepositoryException
      *             if a repository error occurs
      */
-    private void setSender(Node node, MailAddress sender) throws 
RepositoryException {
-        node.setProperty("james:sender", sender.toString());
+    private void setSender(Node node, MaybeSender sender) throws 
RepositoryException {
+        node.setProperty("james:sender", sender.asString());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
----------------------------------------------------------------------
diff --git 
a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
 
b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
index 0c95dd5..4839de7 100644
--- 
a/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
+++ 
b/server/data/data-jdbc/src/main/java/org/apache/james/mailrepository/jdbc/JDBCMailRepository.java
@@ -435,10 +435,10 @@ public class JDBCMailRepository extends 
AbstractMailRepository {
                     updateMessage = 
conn.prepareStatement(sqlQueries.getSqlString("updateMessageSQL", true));
                     updateMessage.setString(1, mc.getState());
                     updateMessage.setString(2, mc.getErrorMessage());
-                    if (mc.getSender() == null) {
+                    if (mc.getMaybeSender().isNullSender()) {
                         updateMessage.setNull(3, java.sql.Types.VARCHAR);
                     } else {
-                        updateMessage.setString(3, mc.getSender().toString());
+                        updateMessage.setString(3, 
mc.getMaybeSender().get().toString());
                     }
                     StringBuilder recipients = new StringBuilder();
                     for (Iterator<MailAddress> i = 
mc.getRecipients().iterator(); i.hasNext();) {
@@ -529,10 +529,10 @@ public class JDBCMailRepository extends 
AbstractMailRepository {
                     insertMessage.setString(2, repositoryName);
                     insertMessage.setString(3, mc.getState());
                     insertMessage.setString(4, mc.getErrorMessage());
-                    if (mc.getSender() == null) {
+                    if (mc.getMaybeSender().isNullSender()) {
                         insertMessage.setNull(5, Types.VARCHAR);
                     } else {
-                        insertMessage.setString(5, mc.getSender().toString());
+                        insertMessage.setString(5, 
mc.getMaybeSender().get().toString());
                     }
                     StringBuilder recipients = new StringBuilder();
                     for (Iterator<MailAddress> i = 
mc.getRecipients().iterator(); i.hasNext();) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
index 0f4d0cc..879d46f 100644
--- 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
+++ 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
@@ -62,6 +62,7 @@ import org.apache.mailet.base.RFC2822Headers;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.github.fge.lambdas.Throwing;
 import com.google.common.collect.ImmutableSet;
 
 public class JamesMailetContext implements MailetContext, Configurable {
@@ -173,13 +174,13 @@ public class JamesMailetContext implements MailetContext, 
Configurable {
      */
     @Override
     public void bounce(Mail mail, String message, MailAddress bouncer) throws 
MessagingException {
-        if (mail.getSender() == null) {
+        if (!mail.hasSender()) {
             LOGGER.info("Mail to be bounced contains a null (<>) reverse path. 
 No bounce will be sent.");
             return;
         } else {
             // Bounce message goes to the reverse path, not to the Reply-To
             // address
-            LOGGER.info("Processing a bounce request for a message with a 
reverse path of {}", mail.getSender());
+            LOGGER.info("Processing a bounce request for a message with a 
reverse path of {}", mail.getMaybeSender());
         }
 
         MailImpl reply = rawBounce(mail, message);
@@ -216,9 +217,13 @@ public class JamesMailetContext implements MailetContext, 
Configurable {
         MimeMessage reply = (MimeMessage) original.reply(false);
         reply.setSubject("Re: " + original.getSubject());
         reply.setSentDate(new Date());
-        Collection<MailAddress> recipients = new HashSet<>();
-        recipients.add(mail.getSender());
-        InternetAddress[] addr = {new 
InternetAddress(mail.getSender().toString())};
+        Collection<MailAddress> recipients = mail.getMaybeSender().asList();
+        InternetAddress[] addr = mail.getMaybeSender().asOptional()
+            .map(MailAddress::asString)
+            .map(Throwing.function((String s) -> new 
InternetAddress(s)).sneakyThrow())
+            .map(address -> new InternetAddress[]{address})
+            .orElse(new InternetAddress[0]);
+
         reply.setRecipients(Message.RecipientType.TO, addr);
         reply.setFrom(new 
InternetAddress(mail.getRecipients().iterator().next().toString()));
         reply.setText(bounceText);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelProcessor.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelProcessor.java
 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelProcessor.java
index a1ae59a..779545c 100644
--- 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelProcessor.java
+++ 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/CamelProcessor.java
@@ -75,7 +75,7 @@ public class CamelProcessor {
                      .addContext("mailet", mailet.getClass().getSimpleName())
                      .addContext("mail", mail.getName())
                      .addContext("recipients", 
ImmutableList.copyOf(mail.getRecipients()))
-                     .addContext("sender", mail.getSender())
+                     .addContext("sender", mail.getMaybeSender())
                      .build()) {
             MailetPipelineLogging.logBeginOfMailetProcess(mailet, mail);
             mailet.service(mail);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
index 21d721a..7f328fe 100644
--- 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
+++ 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/camel/MatcherSplitter.java
@@ -103,7 +103,7 @@ public class MatcherSplitter {
                          .addContext("state", mail.getState())
                          .addContext("mail", mail.getName())
                          .addContext("recipients", 
ImmutableList.copyOf(mail.getRecipients()))
-                         .addContext("sender", mail.getSender())
+                         .addContext("sender", mail.getMaybeSender())
                          .build()) {
                 // call the matcher
                 matchedRcpts = matcher.match(mail);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/BayesianAnalysis.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/BayesianAnalysis.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/BayesianAnalysis.java
index 7e9c29a..bd84484 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/BayesianAnalysis.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/BayesianAnalysis.java
@@ -294,7 +294,7 @@ public class BayesianAnalysis extends GenericMailet {
 
             if (ignoreLocalSender) {
                 // ignore the message if the sender is local
-                if (mail.getSender() != null && 
getMailetContext().isLocalServer(mail.getSender().getDomain())) {
+                if (isSenderLocal(mail)) {
                     return;
                 }
             }
@@ -323,12 +323,8 @@ public class BayesianAnalysis extends GenericMailet {
             probabilityForm.applyPattern("##0.##%");
             String probabilityString = probabilityForm.format(probability);
 
-            String senderString;
-            if (mail.getSender() == null) {
-                senderString = "null";
-            } else {
-                senderString = mail.getSender().toString();
-            }
+            String senderString = mail.getMaybeSender().asString("null");
+
             if (probability > 0.1) {
                 if (LOGGER.isDebugEnabled()) {
                     LOGGER.debug(headerName + ": " + probabilityString + "; 
From: " + senderString + "; Recipient(s): " + 
getAddressesString(mail.getRecipients()));
@@ -348,6 +344,13 @@ public class BayesianAnalysis extends GenericMailet {
         }
     }
 
+    private boolean isSenderLocal(Mail mail) {
+        return mail.getMaybeSender().asOptional()
+            .map(MailAddress::getDomain)
+            .map(domain -> getMailetContext().isLocalServer(domain))
+            .orElse(false);
+    }
+
     private void loadData(Connection conn) throws java.sql.SQLException {
 
         try {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/Bounce.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/Bounce.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/Bounce.java
index 0d2d1a6..f2072d8 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/Bounce.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/Bounce.java
@@ -237,11 +237,11 @@ public class Bounce extends GenericMailet implements 
RedirectNotify {
 
     @Override
     public void service(Mail originalMail) throws MessagingException {
-        if (originalMail.getSender() == null) {
+        if (!originalMail.hasSender()) {
             passThrough(originalMail);
         } else {
             if (getInitParameters().isDebug()) {
-                LOGGER.debug("Processing a bounce request for a message with a 
reverse path.  The bounce will be sent to {}", originalMail.getSender());
+                LOGGER.debug("Processing a bounce request for a message with a 
reverse path.  The bounce will be sent to {}", originalMail.getMaybeSender());
             }
             ProcessRedirectNotify.from(this).process(originalMail);
         }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/DSNBounce.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/DSNBounce.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/DSNBounce.java
index d03f391..6f10b51 100755
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/DSNBounce.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/DSNBounce.java
@@ -35,6 +35,7 @@ import javax.mail.internet.MimeMessage;
 
 import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.james.core.MailAddress;
+import org.apache.james.core.MaybeSender;
 import org.apache.james.dnsservice.api.DNSService;
 import org.apache.james.javax.MimeMultipartReport;
 import org.apache.james.server.core.MailImpl;
@@ -250,7 +251,7 @@ public class DSNBounce extends GenericMailet implements 
RedirectNotify {
        
             if (getInitParameters().isDebug()) {
                 LOGGER.debug("New mail - sender: {}, recipients: {}, name: {}, 
remoteHost: {}, remoteAddr: {}, state: {}, lastUpdated: {}, errorMessage: {}",
-                        newMail.getSender(), newMail.getRecipients(), 
newMail.getName(), newMail.getRemoteHost(), newMail.getRemoteAddr(), 
newMail.getState(), newMail.getLastUpdated(), newMail.getErrorMessage());
+                        newMail.getMaybeSender(), newMail.getRecipients(), 
newMail.getName(), newMail.getRemoteHost(), newMail.getRemoteAddr(), 
newMail.getState(), newMail.getLastUpdated(), newMail.getErrorMessage());
             }
        
             newMail.setMessage(createBounceMessage(originalMail));
@@ -279,7 +280,7 @@ public class DSNBounce extends GenericMailet implements 
RedirectNotify {
     }
 
     private boolean hasSender(Mail originalMail) {
-        if (originalMail.getSender() == null) {
+        if (!originalMail.hasSender()) {
             if (getInitParameters().isDebug()) {
                 LOGGER.info("Processing a bounce request for a message with an 
empty reverse-path.  No bounce will be sent.");
             }
@@ -313,12 +314,12 @@ public class DSNBounce extends GenericMailet implements 
RedirectNotify {
     }
 
     private List<MailAddress> getSenderAsList(Mail originalMail) {
-        MailAddress reversePath = originalMail.getSender();
+        MaybeSender reversePath = originalMail.getMaybeSender();
+
         if (getInitParameters().isDebug()) {
-            LOGGER.debug("Processing a bounce request for a message with a 
reverse path.  The bounce will be sent to {}", reversePath);
+            LOGGER.debug("Processing a bounce request for a message with a 
reverse path.  The bounce will be sent to {}", reversePath.asString());
         }
-
-        return ImmutableList.of(reversePath);
+        return reversePath.asList();
     }
 
     private MimeMessage createBounceMessage(Mail originalMail) throws 
MessagingException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
index 12f1c5d..a986733 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
@@ -35,6 +35,7 @@ import 
org.apache.james.rrt.api.RecipientRewriteTable.ErrorMappingException;
 import org.apache.james.rrt.api.RecipientRewriteTableException;
 import org.apache.james.rrt.lib.Mapping;
 import org.apache.james.rrt.lib.Mappings;
+import org.apache.james.server.core.MailImpl;
 import org.apache.james.util.MemoizedSupplier;
 import org.apache.james.util.OptionalUtils;
 import org.apache.mailet.Mail;
@@ -127,7 +128,14 @@ public class RecipientRewriteTableProcessor {
         RrtExecutionResult executionResults = executeRrtFor(mail);
 
         if (!executionResults.recipientWithError.isEmpty()) {
-            mailetContext.sendMail(mail.getSender(), 
executionResults.recipientWithError, mail.getMessage(), errorProcessor);
+            MailImpl newMail = MailImpl.builder()
+                .name(mail.getName())
+                .sender(mail.getMaybeSender())
+                .recipients(executionResults.recipientWithError)
+                .mimeMessage(mail.getMessage())
+                .state(errorProcessor)
+                .build();
+            mailetContext.sendMail(newMail);
         }
 
         if (executionResults.newRecipients.isEmpty()) {
@@ -155,7 +163,7 @@ public class RecipientRewriteTableProcessor {
             Mappings mappings = 
virtualTableStore.getMappings(recipient.getLocalPart(), recipient.getDomain());
 
             if (mappings != null && !mappings.isEmpty()) {
-                List<MailAddress> newMailAddresses = handleMappings(mappings, 
mail.getSender(), recipient, mail.getMessage());
+                List<MailAddress> newMailAddresses = handleMappings(mappings, 
mail, recipient, mail.getMessage());
                 return RrtExecutionResult.success(newMailAddresses);
             }
             return RrtExecutionResult.success(recipient);
@@ -166,14 +174,14 @@ public class RecipientRewriteTableProcessor {
     }
 
     @VisibleForTesting
-    List<MailAddress> handleMappings(Mappings mappings, MailAddress sender, 
MailAddress recipient, MimeMessage message) throws MessagingException {
+    List<MailAddress> handleMappings(Mappings mappings, Mail mail, MailAddress 
recipient, MimeMessage message) throws MessagingException {
         ImmutableList<MailAddress> mailAddresses = mappings.asStream()
             .map(mapping -> mapping.appendDomainIfNone(defaultDomainSupplier))
             .map(Mapping::asMailAddress)
             .flatMap(OptionalUtils::toStream)
             .collect(Guavate.toImmutableList());
 
-        forwardToRemoteAddress(sender, recipient, message, mailAddresses);
+        forwardToRemoteAddress(mail, recipient, message, mailAddresses);
 
         return getLocalAddresses(mailAddresses);
     }
@@ -184,14 +192,20 @@ public class RecipientRewriteTableProcessor {
             .collect(Guavate.toImmutableList());
     }
 
-    private void forwardToRemoteAddress(MailAddress sender, MailAddress 
recipient, MimeMessage message, ImmutableList<MailAddress> mailAddresses) {
+    private void forwardToRemoteAddress(Mail mail, MailAddress recipient, 
MimeMessage message, ImmutableList<MailAddress> mailAddresses) {
         ImmutableList<MailAddress> remoteAddresses = mailAddresses.stream()
             .filter(mailAddress -> 
!mailetContext.isLocalServer(mailAddress.getDomain()))
             .collect(Guavate.toImmutableList());
 
         if (!remoteAddresses.isEmpty()) {
             try {
-                mailetContext.sendMail(sender, remoteAddresses, message);
+                mailetContext.sendMail(
+                    MailImpl.builder()
+                        .name(mail.getName())
+                        .sender(mail.getMaybeSender())
+                        .recipients(remoteAddresses)
+                        .mimeMessage(message)
+                        .build());
                 LOGGER.info("Mail for {} forwarded to {}", recipient, 
remoteAddresses);
             } catch (MessagingException ex) {
                 LOGGER.warn("Error forwarding mail to {}", remoteAddresses);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
index 238fed8..48bcf65 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RemoteDelivery.java
@@ -204,7 +204,7 @@ public class RemoteDelivery extends GenericMailet {
                 serviceWithGateway(mail);
             }
         } else {
-            LOGGER.debug("Mail {} from {} has no recipients and can not be 
remotely delivered", mail.getName(), mail.getSender());
+            LOGGER.debug("Mail {} from {} has no recipients and can not be 
remotely delivered", mail.getName(), mail.getMaybeSender());
         }
         mail.setState(Mail.GHOST);
     }

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
index 277cee3..3c71efd 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
@@ -22,7 +22,6 @@ package org.apache.james.transport.mailets;
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
-import org.apache.james.core.MailAddress;
 import org.apache.james.jspf.core.Logger;
 import org.apache.james.jspf.executor.SPFResult;
 import org.apache.james.jspf.impl.DefaultSPF;
@@ -71,17 +70,11 @@ public class SPF extends GenericMailet {
 
     @Override
     public void service(Mail mail) throws MessagingException {
-        String sender;
-        MailAddress senderAddr = mail.getSender();
         String remoteAddr = mail.getRemoteAddr();
         String helo = mail.getRemoteHost();
 
         if (!remoteAddr.equals("127.0.0.1")) {
-            if (senderAddr != null) {
-                sender = senderAddr.toString();
-            } else {
-                sender = "";
-            }
+            String sender = mail.getMaybeSender().asString("");
             SPFResult result = spf.checkSPF(remoteAddr, sender, helo);
             mail.setAttribute(EXPLANATION_ATTRIBUTE, result.getExplanation());
             mail.setAttribute(RESULT_ATTRIBUTE, result.getResult());

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
index 2dce4e6..b3b3b7f 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderDomainRepository.java
@@ -24,6 +24,8 @@ import java.util.Optional;
 import javax.inject.Inject;
 import javax.mail.MessagingException;
 
+import org.apache.james.core.Domain;
+import org.apache.james.core.MailAddress;
 import org.apache.james.mailrepository.api.MailRepository;
 import org.apache.james.mailrepository.api.MailRepositoryStore;
 import org.apache.james.mailrepository.api.MailRepositoryUrl;
@@ -89,7 +91,13 @@ public class ToSenderDomainRepository extends GenericMailet {
 
     @Override
     public void service(Mail mail) throws MessagingException {
-        MailRepositoryUrl repositoryUrl = MailRepositoryUrl.from(urlPrefix + 
mail.getSender().getDomain().asString());
+        String domain = mail.getMaybeSender()
+            .asOptional()
+            .map(MailAddress::getDomain)
+            .map(Domain::asString)
+            .orElse("");
+
+        MailRepositoryUrl repositoryUrl = MailRepositoryUrl.from(urlPrefix + 
domain);
         store(mail, repositoryUrl);
         if (!passThrough) {
             mail.setState(Mail.GHOST);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderFolder.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderFolder.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderFolder.java
index 10e52ea..6340be4 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderFolder.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/ToSenderFolder.java
@@ -79,12 +79,14 @@ public class ToSenderFolder extends GenericMailet {
     }
 
     private void doService(Mail mail) throws MessagingException {
-        MailAddress sender = mail.getSender();
-        String username = retrieveUser(sender);
+        if (mail.hasSender()) {
+            MailAddress sender = mail.getMaybeSender().get();
+            String username = retrieveUser(sender);
 
-        mailboxAppender.append(mail.getMessage(), username, folder);
+            mailboxAppender.append(mail.getMessage(), username, folder);
 
-        LOGGER.error("Local delivery with ToSenderFolder mailet for mail {} 
with sender {} in folder {}", mail.getName(), sender, folder);
+            LOGGER.error("Local delivery with ToSenderFolder mailet for mail 
{} with sender {} in folder {}", mail.getName(), sender, folder);
+        }
     }
 
     private String retrieveUser(MailAddress sender) throws MessagingException {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/WhiteListManager.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/WhiteListManager.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/WhiteListManager.java
index 58b0418..0249c7a 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/WhiteListManager.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/WhiteListManager.java
@@ -244,10 +244,10 @@ public class WhiteListManager extends GenericMailet {
     public void service(Mail mail) throws MessagingException {
 
         // check if it's a local sender
-        MailAddress senderMailAddress = mail.getSender();
-        if (senderMailAddress == null) {
+        if (!mail.hasSender()) {
             return;
         }
+        MailAddress senderMailAddress = mail.getMaybeSender().get();
         if (!getMailetContext().isLocalEmail(senderMailAddress)) {
             // not a local sender, so return
             return;
@@ -375,7 +375,7 @@ public class WhiteListManager extends GenericMailet {
      * Manages a display request.
      */
     private void manageDisplayRequest(Mail mail) throws MessagingException {
-        MailAddress senderMailAddress = mail.getSender();
+        MailAddress senderMailAddress = mail.getMaybeSender().get();
         String senderUser = 
senderMailAddress.getLocalPart().toLowerCase(Locale.US);
         Domain senderHost = senderMailAddress.getDomain();
 
@@ -423,7 +423,7 @@ public class WhiteListManager extends GenericMailet {
      * Manages an insert request.
      */
     private void manageInsertRequest(Mail mail) throws MessagingException {
-        MailAddress senderMailAddress = mail.getSender();
+        MailAddress senderMailAddress = mail.getMaybeSender().get();
         String senderUser = 
senderMailAddress.getLocalPart().toLowerCase(Locale.US);
         Domain senderHost = senderMailAddress.getDomain();
 
@@ -544,7 +544,7 @@ public class WhiteListManager extends GenericMailet {
      * Manages a remove request.
      */
     private void manageRemoveRequest(Mail mail) throws MessagingException {
-        MailAddress senderMailAddress = mail.getSender();
+        MailAddress senderMailAddress = mail.getMaybeSender().get();
         String senderUser = 
senderMailAddress.getLocalPart().toLowerCase(Locale.US);
         Domain senderHost = senderMailAddress.getDomain();
 
@@ -665,7 +665,7 @@ public class WhiteListManager extends GenericMailet {
         try {
             MailAddress notifier = getMailetContext().getPostmaster();
 
-            MailAddress senderMailAddress = mail.getSender();
+            MailAddress senderMailAddress = mail.getMaybeSender().get();
 
             MimeMessage message = mail.getMessage();
             // Create the reply message

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/DeliveryUtils.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/DeliveryUtils.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/DeliveryUtils.java
deleted file mode 100644
index 3385f38..0000000
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/DeliveryUtils.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you 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   *
- *                                                              *
- *   http://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 org.apache.james.transport.mailets.delivery;
-
-import org.apache.james.core.MailAddress;
-
-public class DeliveryUtils {
-
-    public static String prettyPrint(MailAddress mailAddress) {
-        if (mailAddress != null) {
-            return mailAddress.asPrettyString();
-        } else {
-            return "<>";
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/MailDispatcher.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/MailDispatcher.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/MailDispatcher.java
index 502e160..bbc575f 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/MailDispatcher.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/MailDispatcher.java
@@ -28,6 +28,7 @@ import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.james.core.MailAddress;
+import org.apache.james.server.core.MailImpl;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetContext;
 import org.apache.mailet.PerRecipientHeaders.Header;
@@ -68,7 +69,7 @@ public class MailDispatcher {
             return this;
         }
 
-        public MailDispatcher build() throws MessagingException {
+        public MailDispatcher build() {
             Preconditions.checkNotNull(mailStore);
             Preconditions.checkNotNull(mailetContext);
             return new MailDispatcher(mailStore, consume.orElse(CONSUME), 
mailetContext);
@@ -87,7 +88,7 @@ public class MailDispatcher {
     }
 
     public void dispatch(Mail mail) throws MessagingException {
-        Collection<MailAddress> errors =  customizeHeadersAndDeliver(mail);
+        List<MailAddress> errors =  customizeHeadersAndDeliver(mail);
         if (!errors.isEmpty()) {
             // If there were errors, we redirect the email to the ERROR
             // processor.
@@ -96,7 +97,13 @@ public class MailDispatcher {
             // the sender. Note that this email doesn't include any details
             // regarding the details of the failure(s).
             // In the future we may wish to address this.
-            mailetContext.sendMail(mail.getSender(), errors, 
mail.getMessage(), Mail.ERROR);
+            Mail newMail = MailImpl.builder()
+                .sender(mail.getMaybeSender())
+                .recipients(errors)
+                .mimeMessage(mail.getMessage())
+                .state(Mail.ERROR)
+                .build();
+            mailetContext.sendMail(newMail);
         }
         if (consume) {
             // Consume this message
@@ -104,19 +111,19 @@ public class MailDispatcher {
         }
     }
 
-    private Collection<MailAddress> customizeHeadersAndDeliver(Mail mail) 
throws MessagingException {
+    private List<MailAddress> customizeHeadersAndDeliver(Mail mail) throws 
MessagingException {
         MimeMessage message = mail.getMessage();
         // Set Return-Path and remove all other Return-Path headers from the 
message
         // This only works because there is a placeholder inserted by 
MimeMessageWrapper
-        message.setHeader(RFC2822Headers.RETURN_PATH, 
DeliveryUtils.prettyPrint(mail.getSender()));
+        message.setHeader(RFC2822Headers.RETURN_PATH, 
mail.getMaybeSender().asPrettyString());
 
-        Collection<MailAddress> errors = deliver(mail, message);
+        List<MailAddress> errors = deliver(mail, message);
 
         return errors;
     }
 
-    private Collection<MailAddress> deliver(Mail mail, MimeMessage message) {
-        Collection<MailAddress> errors = new ArrayList<>();
+    private List<MailAddress> deliver(Mail mail, MimeMessage message) {
+        List<MailAddress> errors = new ArrayList<>();
         for (MailAddress recipient : mail.getRecipients()) {
             try {
                 Map<String, List<String>> savedHeaders = saveHeaders(mail, 
recipient);

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SimpleMailStore.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SimpleMailStore.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SimpleMailStore.java
index 2db2bf1..41708b8 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SimpleMailStore.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/delivery/SimpleMailStore.java
@@ -66,7 +66,7 @@ public class SimpleMailStore implements MailStore {
             return this;
         }
 
-        public SimpleMailStore build() throws MessagingException {
+        public SimpleMailStore build() {
             Preconditions.checkNotNull(usersRepos);
             Preconditions.checkNotNull(folder);
             Preconditions.checkNotNull(mailboxAppender);
@@ -96,7 +96,7 @@ public class SimpleMailStore implements MailStore {
 
         metric.increment();
         LOGGER.info("Local delivered mail {} successfully from {} to {} in 
folder {} with composedMessageId {}", mail.getName(),
-            DeliveryUtils.prettyPrint(mail.getSender()), 
DeliveryUtils.prettyPrint(recipient), locatedFolder, composedMessageId);
+            mail.getMaybeSender().asString(), recipient.asPrettyString(), 
locatedFolder, composedMessageId);
     }
 
     private String locateFolder(String username, Mail mail) {
@@ -106,7 +106,7 @@ public class SimpleMailStore implements MailStore {
         return folder;
     }
 
-    private String computeUsername(MailAddress recipient) throws 
MessagingException {
+    private String computeUsername(MailAddress recipient) {
         try {
             return usersRepository.getUser(recipient);
         } catch (UsersRepositoryException e) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/8ce35148/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
----------------------------------------------------------------------
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
index 4fff11e..378a77e 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
@@ -59,6 +59,7 @@ public class RedirectAction implements MailAction {
      */
     public void execute(ActionRedirect anAction, Mail aMail, ActionContext 
context) throws MessagingException {
         ActionUtils.detectAndHandleLocalLooping(aMail, context, "redirect");
+
         Collection<MailAddress> recipients = new ArrayList<>(1);
         recipients.add(new MailAddress(new 
InternetAddress(anAction.getAddress())));
         MailAddress sender = aMail.getSender();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to