// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 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 com.google.gerrit.server.mail.send;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.flogger.FluentLogger;
import com.google.common.io.BaseEncoding;
import com.google.common.primitives.Ints;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.Version;
import com.google.gerrit.entities.Address;
import com.google.gerrit.entities.EmailHeader;
import com.google.gerrit.entities.EmailHeader.StringEmailHeader;
import com.google.gerrit.exceptions.EmailException;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.mail.Encryption;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import org.apache.commons.net.smtp.AuthSMTPClient;
import org.apache.commons.net.smtp.SMTPClient;
import org.apache.commons.net.smtp.SMTPReply;
import org.apache.james.mime4j.codec.QuotedPrintableOutputStream;
import org.eclipse.jgit.lib.Config;

/** Sends email via a nearby SMTP server. */
@Singleton
public class SmtpEmailSender implements EmailSender {
  /** The socket's connect timeout (0 = infinite timeout) */
  private static final int DEFAULT_CONNECT_TIMEOUT = 0;

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class SmtpEmailSenderModule extends AbstractModule {
    @Override
    protected void configure() {
      bind(EmailSender.class).to(SmtpEmailSender.class);
    }
  }

  private final boolean enabled;
  private final int connectTimeout;

  private String smtpHost;
  private int smtpPort;
  private String smtpUser;
  private String smtpPass;
  private Encryption smtpEncryption;
  private boolean sslVerify;
  private Set<String> allowrcpt;
  private Set<String> denyrcpt;
  private String importance;
  private int expiryDays;

  @Inject
  SmtpEmailSender(@GerritServerConfig Config cfg) {
    enabled = cfg.getBoolean("sendemail", null, "enable", true);
    connectTimeout =
        Ints.checkedCast(
            ConfigUtil.getTimeUnit(
                cfg,
                "sendemail",
                null,
                "connectTimeout",
                DEFAULT_CONNECT_TIMEOUT,
                TimeUnit.MILLISECONDS));

    smtpHost = cfg.getString("sendemail", null, "smtpserver");
    if (smtpHost == null) {
      smtpHost = "127.0.0.1";
    }

    smtpEncryption = cfg.getEnum("sendemail", null, "smtpencryption", Encryption.NONE);
    sslVerify = cfg.getBoolean("sendemail", null, "sslverify", true);

    final int defaultPort;
    switch (smtpEncryption) {
      case SSL:
        defaultPort = 465;
        break;

      case NONE:
      case TLS:
      default:
        defaultPort = 25;
        break;
    }
    smtpPort = cfg.getInt("sendemail", null, "smtpserverport", defaultPort);

    smtpUser = cfg.getString("sendemail", null, "smtpuser");
    smtpPass = cfg.getString("sendemail", null, "smtppass");

    Set<String> rcpt = new HashSet<>();
    Collections.addAll(rcpt, cfg.getStringList("sendemail", null, "allowrcpt"));
    allowrcpt = Collections.unmodifiableSet(rcpt);
    Set<String> rcptdeny = new HashSet<>();
    Collections.addAll(rcptdeny, cfg.getStringList("sendemail", null, "denyrcpt"));
    denyrcpt = Collections.unmodifiableSet(rcptdeny);
    importance = cfg.getString("sendemail", null, "importance");
    expiryDays = cfg.getInt("sendemail", null, "expiryDays", 0);
  }

  @Override
  public boolean isEnabled() {
    return enabled;
  }

  @Override
  public boolean canEmail(String address) {
    if (!isEnabled()) {
      logger.atWarning().log("Not emailing %s (email is disabled)", address);
      return false;
    }

    String domain = address.substring(address.lastIndexOf('@') + 1);
    if (isDenied(address, domain)) {
      return false;
    }

    return isAllowed(address, domain);
  }

  private boolean isDenied(String address, String domain) {

    if (denyrcpt.isEmpty()) {
      return false;
    }

    if (denyrcpt.contains(address)
        || denyrcpt.contains(domain)
        || denyrcpt.contains("@" + domain)) {
      logger.atWarning().log("Not emailing %s (prohibited by sendemail.denyrcpt)", address);
      return true;
    }

    return false;
  }

  private boolean isAllowed(String address, String domain) {

    if (allowrcpt.isEmpty()) {
      return true;
    }

    if (allowrcpt.contains(address)
        || allowrcpt.contains(domain)
        || allowrcpt.contains("@" + domain)) {
      return true;
    }

    logger.atWarning().log("Not emailing %s (prohibited by sendemail.allowrcpt)", address);
    return false;
  }

  @Override
  public void send(
      final Address from,
      Collection<Address> rcpt,
      final Map<String, EmailHeader> callerHeaders,
      String body)
      throws EmailException {
    send(from, rcpt, callerHeaders, body, null);
  }

  @Override
  public void send(
      final Address from,
      Collection<Address> rcpt,
      final Map<String, EmailHeader> callerHeaders,
      String textBody,
      @Nullable String htmlBody)
      throws EmailException {
    if (!isEnabled()) {
      throw new EmailException("Sending email is disabled");
    }

    StringBuilder rejected = new StringBuilder();
    try {
      final SMTPClient client = open();
      try {
        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
         * because some users get rejected.  If not, a single rejected
         * project watcher could prevent email for most actions on a project
         * from being sent to any user!  Instead, queue up the errors, and
         * throw an exception after sending the email to get the rejected
         * error(s) logged.
         */
        for (Address addr : rcpt) {
          if (!client.addRecipient(addr.email())) {
            String error = client.getReplyString();
            rejected
                .append("Server ")
                .append(smtpHost)
                .append(" rejected recipient ")
                .append(addr)
                .append(": ")
                .append(error);
          }
        }

        try (Writer messageDataWriter = client.sendMessageData()) {
          if (messageDataWriter == null) {
            /* Include rejected recipient error messages here to not lose that
             * information. That piece of the puzzle is vital if zero recipients
             * are accepted and the server consequently rejects the DATA command.
             */
            throw new EmailException(
                rejected
                    .append("Server ")
                    .append(smtpHost)
                    .append(" rejected DATA command: ")
                    .append(client.getReplyString())
                    .toString());
          }

          render(messageDataWriter, callerHeaders, textBody, htmlBody);

          if (!client.completePendingCommand()) {
            throw new EmailException(
                "Server " + smtpHost + " rejected message body: " + client.getReplyString());
          }

          client.logout();
          if (rejected.length() > 0) {
            throw new EmailException(rejected.toString());
          }
        }
      } finally {
        client.disconnect();
      }
    } catch (IOException e) {
      throw new EmailException("Cannot send outgoing email", e);
    }
  }

  private void render(
      Writer out,
      Map<String, EmailHeader> callerHeaders,
      String textBody,
      @Nullable String htmlBody)
      throws IOException, EmailException {
    final Map<String, EmailHeader> hdrs = new LinkedHashMap<>(callerHeaders);
    setMissingHeader(hdrs, "MIME-Version", "1.0");
    setMissingHeader(hdrs, "Content-Transfer-Encoding", "8bit");
    setMissingHeader(hdrs, "Content-Disposition", "inline");
    setMissingHeader(hdrs, "User-Agent", "Gerrit/" + Version.getVersion());
    if (importance != null) {
      setMissingHeader(hdrs, "Importance", importance);
    }
    if (expiryDays > 0) {
      Instant expiry = Instant.ofEpochMilli(TimeUtil.nowMs() + expiryDays * 24 * 60 * 60 * 1000L);
      DateTimeFormatter fmt =
          DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss Z")
              .withZone(ZoneId.systemDefault());
      setMissingHeader(hdrs, "Expiry-Date", fmt.format(expiry));
    }

    String encodedBody;
    if (htmlBody == null) {
      setMissingHeader(hdrs, "Content-Type", "text/plain; charset=UTF-8");
      encodedBody = textBody;
    } else {
      String boundary = generateMultipartBoundary(textBody, htmlBody);
      setMissingHeader(
          hdrs,
          "Content-Type",
          "multipart/alternative; boundary=\"" + boundary + "\"; charset=UTF-8");
      encodedBody = buildMultipartBody(boundary, textBody, htmlBody);
    }

    try (Writer w = new BufferedWriter(out)) {
      for (Map.Entry<String, EmailHeader> h : hdrs.entrySet()) {
        if (!h.getValue().isEmpty()) {
          w.write(h.getKey());
          w.write(": ");
          h.getValue().write(w);
          w.write("\r\n");
        }
      }

      w.write("\r\n");
      w.write(encodedBody);
      w.flush();
    }
  }

  public static String generateMultipartBoundary(String textBody, String htmlBody)
      throws EmailException {
    byte[] bytes = new byte[8];
    ThreadLocalRandom rng = ThreadLocalRandom.current();

    // The probability of the boundary being valid is approximately
    // (2^64 - len(message)) / 2^64.
    //
    // The message is much shorter than 2^64 bytes, so if two tries don't
    // suffice, something is seriously wrong.
    for (int i = 0; i < 2; i++) {
      rng.nextBytes(bytes);
      String boundary = BaseEncoding.base64().encode(bytes);
      String encBoundary = "--" + boundary;
      if (textBody.contains(encBoundary) || htmlBody.contains(encBoundary)) {
        continue;
      }
      return boundary;
    }
    throw new EmailException("Gave up generating unique MIME boundary");
  }

  protected String buildMultipartBody(String boundary, String textPart, String htmlPart)
      throws IOException {
    String encodedTextPart = quotedPrintableEncode(textPart);
    String encodedHtmlPart = quotedPrintableEncode(htmlPart);

    // Only declare quoted-printable encoding if there are characters that need to be encoded.
    String textTransferEncoding = textPart.equals(encodedTextPart) ? "7bit" : "quoted-printable";
    String htmlTransferEncoding = htmlPart.equals(encodedHtmlPart) ? "7bit" : "quoted-printable";

    return
    // Output the text part:
    "--"
        + boundary
        + "\r\n"
        + "Content-Type: text/plain; charset=UTF-8\r\n"
        + "Content-Transfer-Encoding: "
        + textTransferEncoding
        + "\r\n"
        + "\r\n"
        + encodedTextPart
        + "\r\n"

        // Output the HTML part:
        + "--"
        + boundary
        + "\r\n"
        + "Content-Type: text/html; charset=UTF-8\r\n"
        + "Content-Transfer-Encoding: "
        + htmlTransferEncoding
        + "\r\n"
        + "\r\n"
        + encodedHtmlPart
        + "\r\n"

        // Output the closing boundary.
        + "--"
        + boundary
        + "--\r\n";
  }

  protected String quotedPrintableEncode(String input) throws IOException {
    ByteArrayOutputStream s = new ByteArrayOutputStream();
    try (QuotedPrintableOutputStream qp = new QuotedPrintableOutputStream(s, false)) {
      qp.write(input.getBytes(UTF_8));
    }
    return s.toString(UTF_8);
  }

  private static void setMissingHeader(Map<String, EmailHeader> hdrs, String name, String value) {
    if (!hdrs.containsKey(name) || hdrs.get(name).isEmpty()) {
      hdrs.put(name, new StringEmailHeader(value));
    }
  }

  private SMTPClient open() throws EmailException {
    final AuthSMTPClient client = new AuthSMTPClient(smtpEncryption == Encryption.SSL, sslVerify);

    client.setConnectTimeout(connectTimeout);
    try {
      client.connect(smtpHost, smtpPort);
      int replyCode = client.getReplyCode();
      String replyString = client.getReplyString();
      if (!SMTPReply.isPositiveCompletion(replyCode)) {
        throw new EmailException(
            String.format("SMTP server rejected connection: %d: %s", replyCode, replyString));
      }
      if (!client.login()) {
        throw new EmailException("SMTP server rejected HELO/EHLO greeting: " + replyString);
      }

      if (smtpEncryption == Encryption.TLS) {
        if (!client.execTLS()) {
          throw new EmailException("SMTP server does not support TLS");
        }
        if (!client.login()) {
          throw new EmailException("SMTP server rejected login: " + replyString);
        }
      }

      if (smtpUser != null && !client.auth(smtpUser, smtpPass)) {
        throw new EmailException("SMTP server rejected auth: " + replyString);
      }
      return client;
    } catch (IOException | EmailException e) {
      if (client.isConnected()) {
        try {
          client.disconnect();
        } catch (IOException e2) {
          // Ignored
        }
      }
      if (e instanceof EmailException) {
        throw (EmailException) e;
      }
      throw new EmailException(e.getMessage(), e);
    }
  }
}
