Make Address an AutoValue

Address is a data-holder for an RFC email address. Making it an
AutoValue signifies to callers that it's immutable, hence thread-safe.

Change-Id: I9deb50145d10feb93eca540701944cea6428f9d1
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index b6e6d46..2afdad99 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -1277,7 +1277,7 @@
   }
 
   protected void assertNotifyTo(String expectedEmail, String expectedFullname) {
-    Address expectedAddress = new Address(expectedFullname, expectedEmail);
+    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
     assertThat(m.rcpt()).containsExactly(expectedAddress);
@@ -1291,7 +1291,7 @@
   }
 
   protected void assertNotifyCc(String expectedEmail, String expectedFullname) {
-    Address expectedAddress = new Address(expectedFullname, expectedEmail);
+    Address expectedAddress = Address.create(expectedFullname, expectedEmail);
     assertNotifyCc(expectedAddress);
   }
 
@@ -1315,7 +1315,7 @@
   protected void assertNotifyBcc(String expectedEmail, String expectedFullName) {
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
-    assertThat(m.rcpt()).containsExactly(new Address(expectedFullName, expectedEmail));
+    assertThat(m.rcpt()).containsExactly(Address.create(expectedFullName, expectedEmail));
     assertThat(m.headers().get("To").isEmpty()).isTrue();
     assertThat(m.headers().get("Cc").isEmpty()).isTrue();
   }
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index 4322f63..bb3901e 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -126,7 +126,7 @@
       recipients.put(
           BCC,
           message.rcpt().stream()
-              .map(Address::getEmail)
+              .map(Address::email)
               .filter(e -> !recipients.get(TO).contains(e) && !recipients.get(CC).contains(e))
               .collect(toList()));
       this.users = users;
@@ -174,7 +174,7 @@
       }
       Truth.assertThat(header).isInstanceOf(AddressList.class);
       AddressList addrList = (AddressList) header;
-      return addrList.getAddressList().stream().map(Address::getEmail).collect(toList());
+      return addrList.getAddressList().stream().map(Address::email).collect(toList());
     }
 
     public FakeEmailSenderSubject to(String... emails) {
diff --git a/java/com/google/gerrit/acceptance/TestAccount.java b/java/com/google/gerrit/acceptance/TestAccount.java
index 87ce70a..a7a4a89 100644
--- a/java/com/google/gerrit/acceptance/TestAccount.java
+++ b/java/com/google/gerrit/acceptance/TestAccount.java
@@ -92,6 +92,6 @@
     //    emailAddress().
     //  * Address#equals only considers email, not name, whereas TestAccount#equals should include
     //    name.
-    return new Address(fullName(), email());
+    return Address.create(fullName(), email());
   }
 }
diff --git a/java/com/google/gerrit/mail/Address.java b/java/com/google/gerrit/mail/Address.java
index 455cc90..520a4c8 100644
--- a/java/com/google/gerrit/mail/Address.java
+++ b/java/com/google/gerrit/mail/Address.java
@@ -14,10 +14,12 @@
 
 package com.google.gerrit.mail;
 
+import com.google.auto.value.AutoValue;
 import com.google.gerrit.common.Nullable;
 
 /** Represents an address (name + email) in an email message. */
-public class Address {
+@AutoValue
+public abstract class Address {
   public static Address parse(String in) {
     final int lt = in.indexOf('<');
     final int gt = in.indexOf('>');
@@ -33,11 +35,11 @@
       if (name.endsWith("\"")) {
         nameEnd--;
       }
-      return new Address(name.length() > 0 ? name.substring(nameStart, nameEnd) : null, email);
+      return Address.create(name.length() > 0 ? name.substring(nameStart, nameEnd) : null, email);
     }
 
     if (lt < 0 && gt < 0 && 0 < at && at < in.length() - 1) {
-      return new Address(in);
+      return Address.create(in);
     }
 
     throw new IllegalArgumentException("Invalid email address: " + in);
@@ -51,60 +53,52 @@
     }
   }
 
-  @Nullable private final String name;
-  private final String email;
-
-  public Address(String email) {
-    this(null, email);
+  public static Address create(String email) {
+    return create(null, email);
   }
 
-  public Address(String name, String email) {
-    this.name = name;
-    this.email = email;
+  public static Address create(String name, String email) {
+    return new AutoValue_Address(name, email);
   }
 
   @Nullable
-  public String getName() {
-    return name;
-  }
+  public abstract String name();
 
-  public String getEmail() {
-    return email;
+  public abstract String email();
+
+  @Override
+  public final int hashCode() {
+    return email().hashCode();
   }
 
   @Override
-  public int hashCode() {
-    return email.hashCode();
-  }
-
-  @Override
-  public boolean equals(Object other) {
+  public final boolean equals(Object other) {
     if (other instanceof Address) {
-      return email.equals(((Address) other).email);
+      return email().equals(((Address) other).email());
     }
     return false;
   }
 
   @Override
-  public String toString() {
+  public final String toString() {
     return toHeaderString();
   }
 
   public String toHeaderString() {
-    if (name != null) {
-      return quotedPhrase(name) + " <" + email + ">";
+    if (name() != null) {
+      return quotedPhrase(name()) + " <" + email() + ">";
     } else if (isSimple()) {
-      return email;
+      return email();
     }
-    return "<" + email + ">";
+    return "<" + email() + ">";
   }
 
   private static final String MUST_QUOTE_EMAIL = "()<>,;:\\\"[]";
   private static final String MUST_QUOTE_NAME = MUST_QUOTE_EMAIL + "@.";
 
   private boolean isSimple() {
-    for (int i = 0; i < email.length(); i++) {
-      final char c = email.charAt(i);
+    for (int i = 0; i < email().length(); i++) {
+      final char c = email().charAt(i);
       if (c <= ' ' || 0x7F <= c || MUST_QUOTE_EMAIL.indexOf(c) != -1) {
         return false;
       }
diff --git a/java/com/google/gerrit/mail/EmailHeader.java b/java/com/google/gerrit/mail/EmailHeader.java
index 69d5fcd..9b11101 100644
--- a/java/com/google/gerrit/mail/EmailHeader.java
+++ b/java/com/google/gerrit/mail/EmailHeader.java
@@ -183,7 +183,7 @@
     }
 
     public void remove(java.lang.String email) {
-      list.removeIf(address -> address.getEmail().equals(email));
+      list.removeIf(address -> address.email().equals(email));
     }
 
     @Override
diff --git a/java/com/google/gerrit/mail/MailHeaderParser.java b/java/com/google/gerrit/mail/MailHeaderParser.java
index a4a6a03..43b1e31 100644
--- a/java/com/google/gerrit/mail/MailHeaderParser.java
+++ b/java/com/google/gerrit/mail/MailHeaderParser.java
@@ -29,7 +29,7 @@
   public static MailMetadata parse(MailMessage m) {
     MailMetadata metadata = new MailMetadata();
     // Find author
-    metadata.author = m.from().getEmail();
+    metadata.author = m.from().email();
 
     // Check email headers for X-Gerrit-<Name>
     for (String header : m.additionalHeaders()) {
diff --git a/java/com/google/gerrit/mail/RawMailParser.java b/java/com/google/gerrit/mail/RawMailParser.java
index 9c89d19..4e005a5 100644
--- a/java/com/google/gerrit/mail/RawMailParser.java
+++ b/java/com/google/gerrit/mail/RawMailParser.java
@@ -71,16 +71,16 @@
     // Add From, To and Cc
     if (mimeMessage.getFrom() != null && !mimeMessage.getFrom().isEmpty()) {
       Mailbox from = mimeMessage.getFrom().get(0);
-      messageBuilder.from(new Address(from.getName(), from.getAddress()));
+      messageBuilder.from(Address.create(from.getName(), from.getAddress()));
     }
     if (mimeMessage.getTo() != null) {
       for (Mailbox m : mimeMessage.getTo().flatten()) {
-        messageBuilder.addTo(new Address(m.getName(), m.getAddress()));
+        messageBuilder.addTo(Address.create(m.getName(), m.getAddress()));
       }
     }
     if (mimeMessage.getCc() != null) {
       for (Mailbox m : mimeMessage.getCc().flatten()) {
-        messageBuilder.addCc(new Address(m.getName(), m.getAddress()));
+        messageBuilder.addCc(Address.create(m.getName(), m.getAddress()));
       }
     }
 
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index b464104..8c4f275 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -786,7 +786,7 @@
 
   private Collection<AccountInfo> toAccountInfoByEmail(Collection<Address> addresses) {
     return addresses.stream()
-        .map(a -> new AccountInfo(a.getName(), a.getEmail()))
+        .map(a -> new AccountInfo(a.name(), a.email()))
         .sorted(AccountInfoComparator.ORDER_NULLS_FIRST)
         .collect(toList());
   }
diff --git a/java/com/google/gerrit/server/change/ReviewerAdder.java b/java/com/google/gerrit/server/change/ReviewerAdder.java
index b55b88d..d9462bf 100644
--- a/java/com/google/gerrit/server/change/ReviewerAdder.java
+++ b/java/com/google/gerrit/server/change/ReviewerAdder.java
@@ -379,7 +379,7 @@
     }
 
     Address adr = Address.tryParse(input.reviewer);
-    if (adr == null || !validator.isValid(adr.getEmail())) {
+    if (adr == null || !validator.isValid(adr.email())) {
       return fail(
           input,
           FailureType.NOT_FOUND,
@@ -481,7 +481,7 @@
         }
         accountLoaderFactory.create(true).fill(result.ccs);
         for (Address a : opResult.addedCCsByEmail()) {
-          result.ccs.add(new AccountInfo(a.getName(), a.getEmail()));
+          result.ccs.add(new AccountInfo(a.name(), a.email()));
         }
       } else {
         result.reviewers = Lists.newArrayListWithCapacity(opResult.addedReviewers().size());
@@ -496,7 +496,7 @@
         }
         accountLoaderFactory.create(true).fill(result.reviewers);
         for (Address a : opResult.addedReviewersByEmail()) {
-          result.reviewers.add(ReviewerInfo.byEmail(a.getName(), a.getEmail()));
+          result.reviewers.add(ReviewerInfo.byEmail(a.name(), a.email()));
         }
       }
     }
diff --git a/java/com/google/gerrit/server/change/ReviewerJson.java b/java/com/google/gerrit/server/change/ReviewerJson.java
index 6686ed8..39e5f74 100644
--- a/java/com/google/gerrit/server/change/ReviewerJson.java
+++ b/java/com/google/gerrit/server/change/ReviewerJson.java
@@ -75,7 +75,7 @@
       ReviewerInfo info;
       if (rsrc.isByEmail()) {
         Address address = rsrc.getReviewerByEmail();
-        info = ReviewerInfo.byEmail(address.getName(), address.getEmail());
+        info = ReviewerInfo.byEmail(address.name(), address.email());
       } else {
         Account.Id reviewerAccountId = rsrc.getReviewerUser().getAccountId();
         info = format(new ReviewerInfo(reviewerAccountId.get()), reviewerAccountId, cd);
diff --git a/java/com/google/gerrit/server/index/change/ChangeField.java b/java/com/google/gerrit/server/index/change/ChangeField.java
index 2be1324..bdb58b8 100644
--- a/java/com/google/gerrit/server/index/change/ChangeField.java
+++ b/java/com/google/gerrit/server/index/change/ChangeField.java
@@ -384,9 +384,9 @@
         reviewersByEmail.asTable().cellSet()) {
       String v = getReviewerByEmailFieldValue(c.getRowKey(), c.getColumnKey());
       r.add(v);
-      if (c.getColumnKey().getName() != null) {
+      if (c.getColumnKey().name() != null) {
         // Add another entry without the name to provide search functionality on the email
-        Address emailOnly = new Address(c.getColumnKey().getEmail());
+        Address emailOnly = Address.create(c.getColumnKey().email());
         r.add(getReviewerByEmailFieldValue(c.getRowKey(), emailOnly));
       }
       r.add(v + ',' + c.getValue().getTime());
diff --git a/java/com/google/gerrit/server/mail/ListMailFilter.java b/java/com/google/gerrit/server/mail/ListMailFilter.java
index 1549f8d..23f7e12 100644
--- a/java/com/google/gerrit/server/mail/ListMailFilter.java
+++ b/java/com/google/gerrit/server/mail/ListMailFilter.java
@@ -52,7 +52,7 @@
       return true;
     }
 
-    boolean match = mailPattern.matcher(message.from().getEmail()).find();
+    boolean match = mailPattern.matcher(message.from().email()).find();
     if ((mode == ListFilterMode.WHITELIST && !match)
         || (mode == ListFilterMode.BLACKLIST && match)) {
       logger.atInfo().log("Mail message from %s rejected by list filter", message.from());
diff --git a/java/com/google/gerrit/server/mail/send/AddKeySender.java b/java/com/google/gerrit/server/mail/send/AddKeySender.java
index 35b0027..3b7b2aa 100644
--- a/java/com/google/gerrit/server/mail/send/AddKeySender.java
+++ b/java/com/google/gerrit/server/mail/send/AddKeySender.java
@@ -58,7 +58,7 @@
   protected void init() throws EmailException {
     super.init();
     setHeader("Subject", String.format("[Gerrit Code Review] New %s Keys Added", getKeyType()));
-    add(RecipientType.TO, new Address(getEmail()));
+    add(RecipientType.TO, Address.create(getEmail()));
   }
 
   @Override
diff --git a/java/com/google/gerrit/server/mail/send/DeleteKeySender.java b/java/com/google/gerrit/server/mail/send/DeleteKeySender.java
index c26e336..3df7f05 100644
--- a/java/com/google/gerrit/server/mail/send/DeleteKeySender.java
+++ b/java/com/google/gerrit/server/mail/send/DeleteKeySender.java
@@ -63,7 +63,7 @@
   protected void init() throws EmailException {
     super.init();
     setHeader("Subject", String.format("[Gerrit Code Review] %s Keys Deleted", getKeyType()));
-    add(RecipientType.TO, new Address(getEmail()));
+    add(RecipientType.TO, Address.create(getEmail()));
   }
 
   @Override
diff --git a/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java b/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
index 55f2352..dfaabbe 100644
--- a/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
+++ b/java/com/google/gerrit/server/mail/send/FromAddressGeneratorProvider.java
@@ -52,8 +52,7 @@
 
     if (from == null || "MIXED".equalsIgnoreCase(from)) {
       ParameterizedString name = new ParameterizedString("${user} (Code Review)");
-      generator =
-          new PatternGen(srvAddr, accountCache, anonymousCowardName, name, srvAddr.getEmail());
+      generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, srvAddr.email());
     } else if ("USER".equalsIgnoreCase(from)) {
       String[] domains = cfg.getStringList("sendemail", null, "allowedDomain");
       Pattern domainPattern = MailUtil.glob(domains);
@@ -64,18 +63,17 @@
       generator = new ServerGen(srvAddr);
     } else {
       final Address a = Address.parse(from);
-      final ParameterizedString name =
-          a.getName() != null ? new ParameterizedString(a.getName()) : null;
+      final ParameterizedString name = a.name() != null ? new ParameterizedString(a.name()) : null;
       if (name == null || name.getParameterNames().isEmpty()) {
         generator = new ServerGen(a);
       } else {
-        generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, a.getEmail());
+        generator = new PatternGen(srvAddr, accountCache, anonymousCowardName, name, a.email());
       }
     }
   }
 
   private static Address toAddress(PersonIdent myIdent) {
-    return new Address(myIdent.getName(), myIdent.getEmailAddress());
+    return Address.create(myIdent.getName(), myIdent.getEmailAddress());
   }
 
   @Override
@@ -127,7 +125,7 @@
         String fullName = a.map(Account::fullName).orElse(null);
         String userEmail = a.map(Account::preferredEmail).orElse(null);
         if (canRelay(userEmail)) {
-          return new Address(fullName, userEmail);
+          return Address.create(fullName, userEmail);
         }
 
         if (fullName == null || "".equals(fullName.trim())) {
@@ -135,17 +133,17 @@
         }
         senderName = nameRewriteTmpl.replace("user", fullName).toString();
       } else {
-        senderName = serverAddress.getName();
+        senderName = serverAddress.name();
       }
 
       String senderEmail;
-      ParameterizedString senderEmailPattern = new ParameterizedString(serverAddress.getEmail());
+      ParameterizedString senderEmailPattern = new ParameterizedString(serverAddress.email());
       if (senderEmailPattern.getParameterNames().isEmpty()) {
         senderEmail = senderEmailPattern.getRawPattern();
       } else {
         senderEmail = senderEmailPattern.replace("userHash", hashOf(senderName)).toString();
       }
-      return new Address(senderName, senderEmail);
+      return Address.create(senderName, senderEmail);
     }
 
     /** check if Gerrit is allowed to send from {@code userEmail}. */
@@ -215,7 +213,7 @@
         senderName = namePattern.replace("user", fullName).toString();
 
       } else {
-        senderName = serverAddress.getName();
+        senderName = serverAddress.name();
       }
 
       String senderEmail;
@@ -224,7 +222,7 @@
       } else {
         senderEmail = senderEmailPattern.replace("userHash", hashOf(senderName)).toString();
       }
-      return new Address(senderName, senderEmail);
+      return Address.create(senderName, senderEmail);
     }
   }
 
diff --git a/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java b/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
index d792b48..cec2bb5 100644
--- a/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
+++ b/java/com/google/gerrit/server/mail/send/HttpPasswordUpdateSender.java
@@ -42,7 +42,7 @@
   protected void init() throws EmailException {
     super.init();
     setHeader("Subject", "[Gerrit Code Review] HTTP password was " + operation);
-    add(RecipientType.TO, new Address(getEmail()));
+    add(RecipientType.TO, Address.create(getEmail()));
   }
 
   @Override
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index 528755a..b35bbec 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -162,7 +162,7 @@
                 "Removing account %s from HTML email because user prefers plain text emails", id);
             removeUser(thisUserAccount);
             smtpRcptToPlaintextOnly.add(
-                new Address(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
+                Address.create(thisUserAccount.fullName(), thisUserAccount.preferredEmail()));
           }
         }
         if (smtpRcptTo.isEmpty() && smtpRcptToPlaintextOnly.isEmpty()) {
@@ -179,11 +179,11 @@
         if (fromId != null) {
           Address address = toAddress(fromId);
           if (address != null) {
-            j.add(address.getEmail());
+            j.add(address.email());
           }
         }
-        smtpRcptTo.stream().forEach(a -> j.add(a.getEmail()));
-        smtpRcptToPlaintextOnly.stream().forEach(a -> j.add(a.getEmail()));
+        smtpRcptTo.stream().forEach(a -> j.add(a.email()));
+        smtpRcptToPlaintextOnly.stream().forEach(a -> j.add(a.email()));
         setHeader(FieldName.REPLY_TO, j.toString());
       }
 
@@ -518,16 +518,16 @@
   }
 
   protected void add(RecipientType rt, Address addr, boolean override) {
-    if (addr != null && addr.getEmail() != null && addr.getEmail().length() > 0) {
-      if (!args.validator.isValid(addr.getEmail())) {
-        logger.atWarning().log("Not emailing %s (invalid email address)", addr.getEmail());
-      } else if (args.emailSender.canEmail(addr.getEmail())) {
+    if (addr != null && addr.email() != null && addr.email().length() > 0) {
+      if (!args.validator.isValid(addr.email())) {
+        logger.atWarning().log("Not emailing %s (invalid email address)", addr.email());
+      } else if (args.emailSender.canEmail(addr.email())) {
         if (!smtpRcptTo.add(addr)) {
           if (!override) {
             return;
           }
-          ((EmailHeader.AddressList) headers.get(FieldName.TO)).remove(addr.getEmail());
-          ((EmailHeader.AddressList) headers.get(FieldName.CC)).remove(addr.getEmail());
+          ((EmailHeader.AddressList) headers.get(FieldName.TO)).remove(addr.email());
+          ((EmailHeader.AddressList) headers.get(FieldName.CC)).remove(addr.email());
         }
         switch (rt) {
           case TO:
@@ -554,7 +554,7 @@
     if (!account.isActive() || e == null) {
       return null;
     }
-    return new Address(account.fullName(), e);
+    return Address.create(account.fullName(), e);
   }
 
   protected void setupSoyContext() {
@@ -597,7 +597,7 @@
   protected void removeUser(Account user) {
     String fromEmail = user.preferredEmail();
     for (Iterator<Address> j = smtpRcptTo.iterator(); j.hasNext(); ) {
-      if (j.next().getEmail().equals(fromEmail)) {
+      if (j.next().email().equals(fromEmail)) {
         j.remove();
       }
     }
diff --git a/java/com/google/gerrit/server/mail/send/ProjectWatch.java b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
index d2fa69c..ef58744 100644
--- a/java/com/google/gerrit/server/mail/send/ProjectWatch.java
+++ b/java/com/google/gerrit/server/mail/send/ProjectWatch.java
@@ -185,7 +185,7 @@
       }
       if (!Strings.isNullOrEmpty(group.getEmailAddress())) {
         // If the group has an email address, do not expand membership.
-        matching.emails.add(new Address(group.getEmailAddress()));
+        matching.emails.add(Address.create(group.getEmailAddress()));
         logger.atFine().log(
             "notify group email address %s; skip expanding to members", group.getEmailAddress());
         continue;
diff --git a/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java b/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
index e1daec6..bb2efe6 100644
--- a/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/RegisterNewEmailSender.java
@@ -54,7 +54,7 @@
   protected void init() throws EmailException {
     super.init();
     setHeader("Subject", "[Gerrit Code Review] Email Verification");
-    add(RecipientType.TO, new Address(addr));
+    add(RecipientType.TO, Address.create(addr));
   }
 
   @Override
diff --git a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
index 7207c00..8e53558 100644
--- a/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
+++ b/java/com/google/gerrit/server/mail/send/SmtpEmailSender.java
@@ -206,9 +206,8 @@
     try {
       final SMTPClient client = open();
       try {
-        if (!client.setSender(from.getEmail())) {
-          throw new EmailException(
-              "Server " + smtpHost + " rejected from address " + from.getEmail());
+        if (!client.setSender(from.email())) {
+          throw new EmailException("Server " + smtpHost + " rejected from address " + from.email());
         }
 
         /* Do not prevent the email from being sent to "good" users simply
@@ -219,7 +218,7 @@
          * error(s) logged.
          */
         for (Address addr : rcpt) {
-          if (!client.addRecipient(addr.getEmail())) {
+          if (!client.addRecipient(addr.email())) {
             String error = client.getReplyString();
             rejected
                 .append("Server ")
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 2312134..b8d20ab 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -1077,7 +1077,7 @@
 
     assertThat(sender.getMessages()).hasSize(1);
     Message m = sender.getMessages().get(0);
-    assertThat(m.rcpt()).containsExactly(new Address(email));
+    assertThat(m.rcpt()).containsExactly(Address.create(email));
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index fd681d8..5c786a5 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -1517,7 +1517,7 @@
     List<Message> messages = sender.getMessages();
     assertThat(messages).hasSize(1);
     Message m = messages.get(0);
-    assertThat(m.from().getName()).isEqualTo("Administrator (Code Review)");
+    assertThat(m.from().name()).isEqualTo("Administrator (Code Review)");
     assertThat(m.rcpt()).containsExactly(user.getNameEmail());
     assertThat(m.body()).contains("I'd like you to do a code review");
     assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -1899,7 +1899,7 @@
     List<Message> messages = sender.getMessages();
     assertThat(messages).hasSize(1);
     Message m = messages.get(0);
-    assertThat(m.rcpt()).containsExactly(new Address(fullname, email));
+    assertThat(m.rcpt()).containsExactly(Address.create(fullname, email));
     assertThat(m.body()).contains("Hello " + fullname + ",\n");
     assertThat(m.body()).contains("I'd like you to do a code review.");
     assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -1960,7 +1960,7 @@
     List<Message> messages = sender.getMessages();
     assertThat(messages).hasSize(1);
     Message m = messages.get(0);
-    assertThat(m.rcpt()).containsExactly(new Address(myGroupUserFullname, myGroupUserEmail));
+    assertThat(m.rcpt()).containsExactly(Address.create(myGroupUserFullname, myGroupUserEmail));
     assertThat(m.body()).contains("Hello " + myGroupUserFullname + ",\n");
     assertThat(m.body()).contains("I'd like you to do a code review.");
     assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
@@ -4461,7 +4461,7 @@
     amendChange(r.getChangeId());
     List<Message> messages = sender.getMessages();
     assertThat(messages).hasSize(1);
-    Address address = new Address(fullname, email);
+    Address address = Address.create(fullname, email);
     assertThat(messages.get(0).rcpt()).containsExactly(address);
 
     // Review notification is not sent to users ignoring the change
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index 36c11da..7213a9f 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -1851,7 +1851,8 @@
 
   @Test
   public void pushWithEmailInFooterNotFound() throws Exception {
-    pushWithReviewerInFooter(new Address("No Body", "notarealuser@example.com").toString(), null);
+    pushWithReviewerInFooter(
+        Address.create("No Body", "notarealuser@example.com").toString(), null);
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
index 28c9a9e..d3c0855 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -514,7 +514,7 @@
       TestAccount expected, @Nullable RecipientType expectedRecipientType) {
     String expectedEmail = expected.email();
     String expectedFullName = expected.fullName();
-    Address expectedAddress = new Address(expectedFullName, expectedEmail);
+    Address expectedAddress = Address.create(expectedFullName, expectedEmail);
     assertThat(sender.getMessages()).hasSize(2);
     Message message = sender.getMessages().get(0);
     assertThat(message.body().contains("review")).isTrue();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
index 090146e..843ecc6 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
@@ -368,6 +368,6 @@
   }
 
   private static String toRfcAddressString(AccountInfo info) {
-    return (new Address(info.name, info.email)).toString();
+    return (Address.create(info.name, info.email)).toString();
   }
 }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index 35576b8..94357b9 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -830,7 +830,7 @@
   }
 
   private void assertThatUserIsOnlyReviewer(String changeId) throws Exception {
-    AccountInfo userInfo = new AccountInfo(user.fullName(), user.getNameEmail().getEmail());
+    AccountInfo userInfo = new AccountInfo(user.fullName(), user.getNameEmail().email());
     userInfo._accountId = user.id().get();
     userInfo.username = user.username();
     assertThat(gApi.changes().id(changeId).get().reviewers)
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
index d831b62..a0ebf02 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
@@ -303,7 +303,7 @@
     assertThat(author).email().isEqualTo(input.author.email);
     assertThat(author).name().isEqualTo(input.author.name);
     GitPerson committer = rApi.commit(false).committer;
-    assertThat(committer).email().isEqualTo(admin.getNameEmail().getEmail());
+    assertThat(committer).email().isEqualTo(admin.getNameEmail().email());
   }
 
   @Test
@@ -463,7 +463,7 @@
     GitPerson author = rApi.commit(false).author;
     assertThat(author).email().isEqualTo(in.author.email);
     GitPerson committer = rApi.commit(false).committer;
-    assertThat(committer).email().isEqualTo(admin.getNameEmail().getEmail());
+    assertThat(committer).email().isEqualTo(admin.getNameEmail().email());
   }
 
   @Test
diff --git a/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java b/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
index 7ad8e14..7a80cbd 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/project/ProjectWatchIT.java
@@ -49,7 +49,7 @@
 
   @Test
   public void newPatchSetsNotifyConfig() throws Exception {
-    Address addr = new Address("Watcher", "watcher@example.com");
+    Address addr = Address.create("Watcher", "watcher@example.com");
     NotifyConfig nc = new NotifyConfig();
     nc.addEmail(addr);
     nc.setName("new-patch-set");
@@ -90,7 +90,7 @@
 
   @Test
   public void noNotificationForPrivateChangesForWatchersInNotifyConfig() throws Exception {
-    Address addr = new Address("Watcher", "watcher@example.com");
+    Address addr = Address.create("Watcher", "watcher@example.com");
     NotifyConfig nc = new NotifyConfig();
     nc.addEmail(addr);
     nc.setName("team");
@@ -122,7 +122,7 @@
   @Test
   public void noNotificationForChangeThatIsTurnedPrivateForWatchersInNotifyConfig()
       throws Exception {
-    Address addr = new Address("Watcher", "watcher@example.com");
+    Address addr = Address.create("Watcher", "watcher@example.com");
     NotifyConfig nc = new NotifyConfig();
     nc.addEmail(addr);
     nc.setName("team");
@@ -151,7 +151,7 @@
 
   @Test
   public void noNotificationForWipChangesForWatchersInNotifyConfig() throws Exception {
-    Address addr = new Address("Watcher", "watcher@example.com");
+    Address addr = Address.create("Watcher", "watcher@example.com");
     NotifyConfig nc = new NotifyConfig();
     nc.addEmail(addr);
     nc.setName("team");
@@ -182,7 +182,7 @@
 
   @Test
   public void noNotificationForChangeThatIsTurnedWipForWatchersInNotifyConfig() throws Exception {
-    Address addr = new Address("Watcher", "watcher@example.com");
+    Address addr = Address.create("Watcher", "watcher@example.com");
     NotifyConfig nc = new NotifyConfig();
     nc.addEmail(addr);
     nc.setName("team");
diff --git a/javatests/com/google/gerrit/mail/AbstractParserTest.java b/javatests/com/google/gerrit/mail/AbstractParserTest.java
index 3c84420..f3c8671 100644
--- a/javatests/com/google/gerrit/mail/AbstractParserTest.java
+++ b/javatests/com/google/gerrit/mail/AbstractParserTest.java
@@ -84,7 +84,7 @@
   protected static MailMessage.Builder newMailMessageBuilder() {
     MailMessage.Builder b = MailMessage.builder();
     b.id("id");
-    b.from(new Address("Foo Bar", "foo@bar.com"));
+    b.from(Address.create("Foo Bar", "foo@bar.com"));
     b.dateReceived(Instant.now());
     b.subject("");
     return b;
diff --git a/javatests/com/google/gerrit/mail/AddressTest.java b/javatests/com/google/gerrit/mail/AddressTest.java
index da26123..8addcf8 100644
--- a/javatests/com/google/gerrit/mail/AddressTest.java
+++ b/javatests/com/google/gerrit/mail/AddressTest.java
@@ -23,57 +23,57 @@
   @Test
   public void parse_NameEmail1() {
     final Address a = Address.parse("A U Thor <author@example.com>");
-    assertThat(a.getName()).isEqualTo("A U Thor");
-    assertThat(a.getEmail()).isEqualTo("author@example.com");
+    assertThat(a.name()).isEqualTo("A U Thor");
+    assertThat(a.email()).isEqualTo("author@example.com");
   }
 
   @Test
   public void parse_NameEmail2() {
     final Address a = Address.parse("A <a@b>");
-    assertThat(a.getName()).isEqualTo("A");
-    assertThat(a.getEmail()).isEqualTo("a@b");
+    assertThat(a.name()).isEqualTo("A");
+    assertThat(a.email()).isEqualTo("a@b");
   }
 
   @Test
   public void parse_NameEmail3() {
     final Address a = Address.parse("<a@b>");
-    assertThat(a.getName()).isNull();
-    assertThat(a.getEmail()).isEqualTo("a@b");
+    assertThat(a.name()).isNull();
+    assertThat(a.email()).isEqualTo("a@b");
   }
 
   @Test
   public void parse_NameEmail4() {
     final Address a = Address.parse("A U Thor<author@example.com>");
-    assertThat(a.getName()).isEqualTo("A U Thor");
-    assertThat(a.getEmail()).isEqualTo("author@example.com");
+    assertThat(a.name()).isEqualTo("A U Thor");
+    assertThat(a.email()).isEqualTo("author@example.com");
   }
 
   @Test
   public void parse_NameEmail5() {
     final Address a = Address.parse("A U Thor  <author@example.com>");
-    assertThat(a.getName()).isEqualTo("A U Thor");
-    assertThat(a.getEmail()).isEqualTo("author@example.com");
+    assertThat(a.name()).isEqualTo("A U Thor");
+    assertThat(a.email()).isEqualTo("author@example.com");
   }
 
   @Test
   public void parse_Email1() {
     final Address a = Address.parse("author@example.com");
-    assertThat(a.getName()).isNull();
-    assertThat(a.getEmail()).isEqualTo("author@example.com");
+    assertThat(a.name()).isNull();
+    assertThat(a.email()).isEqualTo("author@example.com");
   }
 
   @Test
   public void parse_Email2() {
     final Address a = Address.parse("a@b");
-    assertThat(a.getName()).isNull();
-    assertThat(a.getEmail()).isEqualTo("a@b");
+    assertThat(a.name()).isNull();
+    assertThat(a.email()).isEqualTo("a@b");
   }
 
   @Test
   public void parse_NewTLD() {
     Address a = Address.parse("A U Thor <author@example.systems>");
-    assertThat(a.getName()).isEqualTo("A U Thor");
-    assertThat(a.getEmail()).isEqualTo("author@example.systems");
+    assertThat(a.name()).isEqualTo("A U Thor");
+    assertThat(a.email()).isEqualTo("author@example.systems");
   }
 
   @Test
@@ -148,6 +148,6 @@
   }
 
   private static String format(String name, String email) {
-    return new Address(name, email).toHeaderString();
+    return Address.create(name, email).toHeaderString();
   }
 }
diff --git a/javatests/com/google/gerrit/mail/MailHeaderParserTest.java b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
index 2d2c2ea..296d1a1 100644
--- a/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
+++ b/javatests/com/google/gerrit/mail/MailHeaderParserTest.java
@@ -38,11 +38,11 @@
     b.addAdditionalHeader(
         MailHeader.COMMENT_DATE.fieldWithDelimiter() + "Tue, 25 Oct 2016 02:11:35 -0700");
 
-    Address author = new Address("Diffy", "test@gerritcodereview.com");
+    Address author = Address.create("Diffy", "test@gerritcodereview.com");
     b.from(author);
 
     MailMetadata meta = MailHeaderParser.parse(b.build());
-    assertThat(meta.author).isEqualTo(author.getEmail());
+    assertThat(meta.author).isEqualTo(author.email());
     assertThat(meta.changeNumber).isEqualTo(123);
     assertThat(meta.patchSet).isEqualTo(1);
     assertThat(meta.messageType).isEqualTo("comment");
@@ -71,11 +71,11 @@
         .append("Tue, 25 Oct 2016 02:11:35 -0700\r\n");
     b.textContent(stringBuilder.toString());
 
-    Address author = new Address("Diffy", "test@gerritcodereview.com");
+    Address author = Address.create("Diffy", "test@gerritcodereview.com");
     b.from(author);
 
     MailMetadata meta = MailHeaderParser.parse(b.build());
-    assertThat(meta.author).isEqualTo(author.getEmail());
+    assertThat(meta.author).isEqualTo(author.email());
     assertThat(meta.changeNumber).isEqualTo(123);
     assertThat(meta.patchSet).isEqualTo(1);
     assertThat(meta.messageType).isEqualTo("comment");
@@ -112,11 +112,11 @@
         .append("</div>");
     b.htmlContent(stringBuilder.toString());
 
-    Address author = new Address("Diffy", "test@gerritcodereview.com");
+    Address author = Address.create("Diffy", "test@gerritcodereview.com");
     b.from(author);
 
     MailMetadata meta = MailHeaderParser.parse(b.build());
-    assertThat(meta.author).isEqualTo(author.getEmail());
+    assertThat(meta.author).isEqualTo(author.email());
     assertThat(meta.changeNumber).isEqualTo(123);
     assertThat(meta.patchSet).isEqualTo(1);
     assertThat(meta.messageType).isEqualTo("comment");
diff --git a/javatests/com/google/gerrit/mail/data/AttachmentMessage.java b/javatests/com/google/gerrit/mail/data/AttachmentMessage.java
index 1d94d68..aea59ba 100644
--- a/javatests/com/google/gerrit/mail/data/AttachmentMessage.java
+++ b/javatests/com/google/gerrit/mail/data/AttachmentMessage.java
@@ -77,8 +77,8 @@
     MailMessage.Builder expect = MailMessage.builder();
     expect
         .id("<CAM7sg=3meaAVUxW3KXeJEVs8sv_ADw1BnvpcHHiYVR2TQQi__w@mail.gmail.com>")
-        .from(new Address("Patrick Hiesel", "hiesel@google.com"))
-        .addTo(new Address("Patrick Hiesel", "hiesel@google.com"))
+        .from(Address.create("Patrick Hiesel", "hiesel@google.com"))
+        .addTo(Address.create("Patrick Hiesel", "hiesel@google.com"))
         .textContent("Contains unwanted attachment")
         .htmlContent("<div dir=\"ltr\">Contains unwanted attachment</div>")
         .subject("Test Subject")
diff --git a/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java b/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
index aa19537..957ee6e 100644
--- a/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
+++ b/javatests/com/google/gerrit/mail/data/Base64HeaderMessage.java
@@ -53,10 +53,10 @@
     expect
         .id("<001a114da7ae26e2eb053fe0c29c@google.com>")
         .from(
-            new Address(
+            Address.create(
                 "Jonathan Nieder (Gerrit)",
                 "noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
-        .addTo(new Address("ekempin", "ekempin@google.com"))
+        .addTo(Address.create("ekempin", "ekempin@google.com"))
         .textContent(textContent)
         .subject("\uD83D\uDE1B test")
         .dateReceived(
diff --git a/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java b/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
index 1d68cc8..e5e2ed8 100644
--- a/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
+++ b/javatests/com/google/gerrit/mail/data/HtmlMimeMessage.java
@@ -91,10 +91,10 @@
     expect
         .id("<001a114cd8be55b4ab053face5cd@google.com>")
         .from(
-            new Address(
+            Address.create(
                 "ekempin (Gerrit)", "noreply-gerritcodereview-qUgXfQecoDLHwp0MldAzig@google.com"))
-        .addCc(new Address("ekempin", "ekempin@google.com"))
-        .addTo(new Address("Patrick Hiesel", "hiesel@google.com"))
+        .addCc(Address.create("ekempin", "ekempin@google.com"))
+        .addTo(Address.create("Patrick Hiesel", "hiesel@google.com"))
         .textContent(textContent)
         .htmlContent(unencodedHtmlContent)
         .subject("Change in gerrit[master]: Implement receiver class structure and bindings")
diff --git a/javatests/com/google/gerrit/mail/data/NonUTF8Message.java b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
index 32915e7..e183a37 100644
--- a/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
+++ b/javatests/com/google/gerrit/mail/data/NonUTF8Message.java
@@ -57,10 +57,10 @@
     expect
         .id("<001a114da7ae26e2eb053fe0c29c@google.com>")
         .from(
-            new Address(
+            Address.create(
                 "Jonathan Nieder (Gerrit)",
                 "noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
-        .addTo(new Address("ekempin", "ekempin@google.com"))
+        .addTo(Address.create("ekempin", "ekempin@google.com"))
         .textContent(textContent)
         .subject("\uD83D\uDE1B test")
         .dateReceived(
diff --git a/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java b/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
index 47e813a..ac739c8 100644
--- a/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
+++ b/javatests/com/google/gerrit/mail/data/QuotedPrintableHeaderMessage.java
@@ -54,10 +54,10 @@
     expect
         .id("<001a114da7ae26e2eb053fe0c29c@google.com>")
         .from(
-            new Address(
+            Address.create(
                 "Jonathan Nieder (Gerrit)",
                 "noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
-        .addTo(new Address("ekempin", "ekempin@google.com"))
+        .addTo(Address.create("ekempin", "ekempin@google.com"))
         .textContent(textContent)
         .subject("âme vulgaire")
         .dateReceived(
diff --git a/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java b/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
index c4737e6..3f8e62f 100644
--- a/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
+++ b/javatests/com/google/gerrit/mail/data/SimpleTextMessage.java
@@ -116,13 +116,13 @@
     expect
         .id("<001a114da7ae26e2eb053fe0c29c@google.com>")
         .from(
-            new Address(
+            Address.create(
                 "Jonathan Nieder (Gerrit)",
                 "noreply-gerritcodereview-CtTy0igsBrnvL7dKoWEIEg@google.com"))
-        .addTo(new Address("ekempin", "ekempin@google.com"))
-        .addCc(new Address("Dave Borowitz", "dborowitz@google.com"))
-        .addCc(new Address("Jonathan Nieder", "jrn@google.com"))
-        .addCc(new Address("Patrick Hiesel", "hiesel@google.com"))
+        .addTo(Address.create("ekempin", "ekempin@google.com"))
+        .addCc(Address.create("Dave Borowitz", "dborowitz@google.com"))
+        .addCc(Address.create("Jonathan Nieder", "jrn@google.com"))
+        .addCc(Address.create("Patrick Hiesel", "hiesel@google.com"))
         .textContent(textContent)
         .subject("Change in gerrit[master]: (Re)enable voting buttons for merged changes")
         .dateReceived(
diff --git a/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java b/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
index 9dcb08c..805c542 100644
--- a/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
+++ b/javatests/com/google/gerrit/server/mail/AutoReplyMailFilterTest.java
@@ -61,8 +61,8 @@
     // Build Message
     MailMessage.Builder b = MailMessage.builder();
     b.id("some id");
-    b.from(new Address("admim@example.com"));
-    b.addTo(new Address("gerrit@my-company.com")); // Not evaluated
+    b.from(Address.create("admim@example.com"));
+    b.addTo(Address.create("gerrit@my-company.com")); // Not evaluated
     b.subject("");
     b.dateReceived(Instant.now());
     b.textContent("I am currently out of office, please leave a code review after the beep.");
diff --git a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
index 74f44a1..a383d56 100644
--- a/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
+++ b/javatests/com/google/gerrit/server/mail/send/FromAddressGeneratorProviderTest.java
@@ -85,8 +85,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name);
-    assertThat(r.getEmail()).isEqualTo(email);
+    assertThat(r.name()).isEqualTo(name);
+    assertThat(r.email()).isEqualTo(email);
     verifyAccountCacheGet(user);
   }
 
@@ -99,8 +99,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isNull();
-    assertThat(r.getEmail()).isEqualTo(email);
+    assertThat(r.name()).isNull();
+    assertThat(r.email()).isEqualTo(email);
     verifyAccountCacheGet(user);
   }
 
@@ -113,8 +113,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name + " (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(name + " (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -123,8 +123,8 @@
     setFrom("USER");
     final Address r = create().from(null);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(ident.getName());
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(ident.getName());
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyZeroInteractions(accountCache);
   }
 
@@ -138,8 +138,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name);
-    assertThat(r.getEmail()).isEqualTo(email);
+    assertThat(r.name()).isEqualTo(name);
+    assertThat(r.email()).isEqualTo(email);
     verifyAccountCacheGet(user);
   }
 
@@ -153,8 +153,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name + " (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(name + " (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -169,8 +169,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name);
-    assertThat(r.getEmail()).isEqualTo(email);
+    assertThat(r.name()).isEqualTo(name);
+    assertThat(r.email()).isEqualTo(email);
     verifyAccountCacheGet(user);
   }
 
@@ -185,8 +185,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name + " (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(name + " (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -200,8 +200,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name);
-    assertThat(r.getEmail()).isEqualTo(email);
+    assertThat(r.name()).isEqualTo(name);
+    assertThat(r.email()).isEqualTo(email);
     verifyAccountCacheGet(user);
   }
 
@@ -227,8 +227,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(ident.getName());
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(ident.getName());
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyZeroInteractions(accountCache);
   }
 
@@ -237,8 +237,8 @@
     setFrom("SERVER");
     final Address r = create().from(null);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(ident.getName());
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(ident.getName());
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyZeroInteractions(accountCache);
   }
 
@@ -264,8 +264,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name + " (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(name + " (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -278,8 +278,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo("Anonymous Coward (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo("Anonymous Coward (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -292,8 +292,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(name + " (Code Review)");
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(name + " (Code Review)");
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyAccountCacheGet(user);
   }
 
@@ -302,8 +302,8 @@
     setFrom("MIXED");
     final Address r = create().from(null);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(ident.getName());
-    assertThat(r.getEmail()).isEqualTo(ident.getEmailAddress());
+    assertThat(r.name()).isEqualTo(ident.getName());
+    assertThat(r.email()).isEqualTo(ident.getEmailAddress());
     verifyZeroInteractions(accountCache);
   }
 
@@ -317,8 +317,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo("A " + name + " B");
-    assertThat(r.getEmail()).isEqualTo("my.server@email.address");
+    assertThat(r.name()).isEqualTo("A " + name + " B");
+    assertThat(r.email()).isEqualTo("my.server@email.address");
     verifyAccountCacheGet(user);
   }
 
@@ -331,8 +331,8 @@
 
     final Address r = create().from(user);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo("A Anonymous Coward B");
-    assertThat(r.getEmail()).isEqualTo("my.server@email.address");
+    assertThat(r.name()).isEqualTo("A Anonymous Coward B");
+    assertThat(r.email()).isEqualTo("my.server@email.address");
   }
 
   @Test
@@ -341,8 +341,8 @@
 
     final Address r = create().from(null);
     assertThat(r).isNotNull();
-    assertThat(r.getName()).isEqualTo(ident.getName());
-    assertThat(r.getEmail()).isEqualTo("my.server@email.address");
+    assertThat(r.name()).isEqualTo(ident.getName());
+    assertThat(r.email()).isEqualTo("my.server@email.address");
   }
 
   private Account.Id user(String name, String email) {
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 10b4eb7..efbaed6 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -431,11 +431,11 @@
                     ImmutableTable.<ReviewerStateInternal, Address, Timestamp>builder()
                         .put(
                             ReviewerStateInternal.CC,
-                            new Address("Name1", "email1@example.com"),
+                            Address.create("Name1", "email1@example.com"),
                             new Timestamp(1212L))
                         .put(
                             ReviewerStateInternal.REVIEWER,
-                            new Address("Name2", "email2@example.com"),
+                            Address.create("Name2", "email2@example.com"),
                             new Timestamp(3434L))
                         .build()))
             .build(),
@@ -465,7 +465,7 @@
                     ReviewerByEmailSet.fromTable(
                         ImmutableTable.of(
                             ReviewerStateInternal.CC,
-                            new Address("emailonly@example.com"),
+                            Address.create("emailonly@example.com"),
                             new Timestamp(1212L))))
                 .build(),
             ChangeNotesStateProto.newBuilder()
@@ -484,8 +484,8 @@
     ImmutableSet<Address> ccs = actual.reviewersByEmail().byState(ReviewerStateInternal.CC);
     assertThat(ccs).hasSize(1);
     Address address = Iterables.getOnlyElement(ccs);
-    assertThat(address.getName()).isNull();
-    assertThat(address.getEmail()).isEqualTo("emailonly@example.com");
+    assertThat(address.name()).isNull();
+    assertThat(address.email()).isEqualTo("emailonly@example.com");
   }
 
   @Test
@@ -525,11 +525,11 @@
                     ImmutableTable.<ReviewerStateInternal, Address, Timestamp>builder()
                         .put(
                             ReviewerStateInternal.CC,
-                            new Address("Name1", "email1@example.com"),
+                            Address.create("Name1", "email1@example.com"),
                             new Timestamp(1212L))
                         .put(
                             ReviewerStateInternal.REVIEWER,
-                            new Address("Name2", "email2@example.com"),
+                            Address.create("Name2", "email2@example.com"),
                             new Timestamp(3434L))
                         .build()))
             .build(),
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 4ec52e3..964187c 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -2920,7 +2920,7 @@
 
   @Test
   public void putReviewerByEmail() throws Exception {
-    Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
+    Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
 
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2933,7 +2933,7 @@
 
   @Test
   public void putAndRemoveReviewerByEmail() throws Exception {
-    Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
+    Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
 
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2950,7 +2950,7 @@
 
   @Test
   public void putRemoveAndAddBackReviewerByEmail() throws Exception {
-    Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
+    Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
 
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2971,8 +2971,8 @@
 
   @Test
   public void putReviewerByEmailAndCcByEmail() throws Exception {
-    Address adrReviewer = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
-    Address adrCc = new Address("Foo Bor", "foo.bar.2@gerritcodereview.com");
+    Address adrReviewer = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
+    Address adrCc = Address.create("Foo Bor", "foo.bar.2@gerritcodereview.com");
 
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -2993,7 +2993,7 @@
 
   @Test
   public void putReviewerByEmailAndChangeToCc() throws Exception {
-    Address adr = new Address("Foo Bar", "foo.bar@gerritcodereview.com");
+    Address adr = Address.create("Foo Bar", "foo.bar@gerritcodereview.com");
 
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
@@ -3049,8 +3049,8 @@
 
   @Test
   public void pendingReviewers() throws Exception {
-    Address adr1 = new Address("Foo Bar1", "foo.bar1@gerritcodereview.com");
-    Address adr2 = new Address("Foo Bar2", "foo.bar2@gerritcodereview.com");
+    Address adr1 = Address.create("Foo Bar1", "foo.bar1@gerritcodereview.com");
+    Address adr2 = Address.create("Foo Bar2", "foo.bar2@gerritcodereview.com");
     Account.Id ownerId = changeOwner.getAccount().id();
     Account.Id otherUserId = otherUser.getAccount().id();
 
diff --git a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
index b32ac19..6a090c1 100644
--- a/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommitMessageOutputTest.java
@@ -388,7 +388,7 @@
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
     update.putReviewerByEmail(
-        new Address("John Doe", "j.doe@gerritcodereview.com"), ReviewerStateInternal.REVIEWER);
+        Address.create("John Doe", "j.doe@gerritcodereview.com"), ReviewerStateInternal.REVIEWER);
     update.commit();
 
     assertBodyEquals(
@@ -401,7 +401,8 @@
   public void ccByEmail() throws Exception {
     Change c = newChange();
     ChangeUpdate update = newUpdate(c, changeOwner);
-    update.putReviewerByEmail(new Address("j.doe@gerritcodereview.com"), ReviewerStateInternal.CC);
+    update.putReviewerByEmail(
+        Address.create("j.doe@gerritcodereview.com"), ReviewerStateInternal.CC);
     update.commit();
 
     assertBodyEquals(