TokenMessageBuilder.java

  1. /*
  2.  * The coLAB project
  3.  * Copyright (C) 2021-2023 AlbaSim, MEI, HEIG-VD, HES-SO
  4.  *
  5.  * Licensed under the MIT License
  6.  */
  7. package ch.colabproject.colab.api.controller.token;

  8. import ch.colabproject.colab.api.model.token.Token;
  9. import java.text.MessageFormat;
  10. import java.time.format.DateTimeFormatter;
  11. import java.util.ArrayList;
  12. import java.util.List;
  13. import java.util.stream.Collectors;
  14. import org.apache.commons.lang3.StringUtils;

  15. /**
  16.  * To build the body of the message to send for a token.
  17.  *
  18.  * @author sandra
  19.  */
  20. public class TokenMessageBuilder {

  21.     /**
  22.      * Text to set as a footer to inform about the validity of the message
  23.      */
  24.     public static final String VALIDITY_FOOTER = "This link can be used until {0} GMT.";

  25.     /**
  26.      * The message title
  27.      */
  28.     private String headTitle;

  29.     /**
  30.      * The message main picture
  31.      */
  32.     private String picture;

  33.     /**
  34.      * The message heading
  35.      */
  36.     private String heading;

  37.     /**
  38.      * The message sub heading
  39.      */
  40.     private String subheading;

  41.     /**
  42.      * The message informations
  43.      */
  44.     private String info;

  45.     /**
  46.      * The link to go to consume the token on co.LAB
  47.      */
  48.     private String linkHref;

  49.     /**
  50.      * The label of the link to go to consume the token on co.LAB
  51.      */
  52.     private String linkLabel;

  53.     /**
  54.      * The message footer info
  55.      */
  56.     private List<String> footer = new ArrayList<>();

  57.     /**
  58.      * Constructor
  59.      *
  60.      * @param token the token for which we are writing a message
  61.      */
  62.     public TokenMessageBuilder(Token token) {
  63.         // this.token = token;
  64.         headTitle = null;
  65.         picture = null;
  66.         heading = null;
  67.         subheading = null;
  68.         info = null;
  69.         linkHref = null;
  70.         linkLabel = null;
  71.         footer = new ArrayList<>();
  72.         if (token.getExpirationDate() != null) {
  73.             footer.add(MessageFormat.format(VALIDITY_FOOTER,
  74.                 token.getExpirationDate().format(DateTimeFormatter.RFC_1123_DATE_TIME)));
  75.         }
  76.     }

  77.     /**
  78.      * Set the message head title
  79.      *
  80.      * @param headTitle the head title to set
  81.      *
  82.      * @return this builder
  83.      */
  84.     public TokenMessageBuilder headTitle(String headTitle) {
  85.         this.headTitle = headTitle;
  86.         return this;
  87.     }

  88.     /**
  89.      * Set the message main picture
  90.      *
  91.      * @param picture the main picture to set
  92.      *
  93.      * @return this builder
  94.      */
  95.     public TokenMessageBuilder picture(String picture) {
  96.         this.picture = picture;
  97.         return this;
  98.     }

  99.     /**
  100.      * Set the message heading
  101.      *
  102.      * @param heading the heading to set
  103.      *
  104.      * @return this builder
  105.      */
  106.     public TokenMessageBuilder heading(String heading) {
  107.         this.heading = heading;
  108.         return this;
  109.     }

  110.     /**
  111.      * Set the message sub heading
  112.      *
  113.      * @param subheading the sub heading to set
  114.      *
  115.      * @return this builder
  116.      */
  117.     public TokenMessageBuilder subheading(String subheading) {
  118.         this.subheading = subheading;
  119.         return this;
  120.     }

  121.     /**
  122.      * Set the message additional content
  123.      *
  124.      * @param info the additional content to set
  125.      *
  126.      * @return this builder
  127.      */
  128.     public TokenMessageBuilder info(String info) {
  129.         this.info = info;
  130.         return this;
  131.     }

  132.     /**
  133.      * Set the message link href
  134.      *
  135.      * @param linkHref the link href to set
  136.      *
  137.      * @return this builder
  138.      */
  139.     public TokenMessageBuilder linkHref(String linkHref) {
  140.         this.linkHref = linkHref;
  141.         return this;
  142.     }

  143.     /**
  144.      * Set the message link label
  145.      *
  146.      * @param linkLabel the link label to set
  147.      *
  148.      * @return this builder
  149.      */
  150.     public TokenMessageBuilder linkLabel(String linkLabel) {
  151.         this.linkLabel = linkLabel;
  152.         return this;
  153.     }

  154.     /**
  155.      * Add a message footer
  156.      *
  157.      * @param footer the footer to add
  158.      *
  159.      * @return this builder
  160.      */
  161.     public TokenMessageBuilder additionalFooter(String footer) {
  162.         this.footer.add(footer);
  163.         return this;
  164.     }

  165.     /**
  166.      * Build the email body to send with the token
  167.      *
  168.      * @return html email body
  169.      */
  170.     public String build() {
  171.         return "<!DOCTYPE html>\n"
  172.             + "<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n"
  173.             + "  <head>\n"
  174.             + "    <meta charset=\"utf-8\" />\n"
  175.             + "    <!-- utf-8 works for most cases -->\n"
  176.             + "    <meta name=\"viewport\" content=\"width=device-width\" />\n"
  177.             + "    <!-- Forcing initial-scale shouldn't be necessary -->\n"
  178.             + "    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n"
  179.             + "    <!-- Use the latest (edge) version of IE rendering engine -->\n"
  180.             + "    <meta name=\"x-apple-disable-message-reformatting\" />\n"
  181.             + "    <!-- Disable auto-scale in iOS 10 Mail entirely -->\n"
  182.             + "    <title>" + headTitle + "</title>\n"
  183.             + "    <!-- The title tag shows in email notifications, like Android 4.4. -->\n"
  184.             + "    <style>\n"
  185.             + "      h2,\n"
  186.             + "      h3 {\n"
  187.             + "        font-family: sans-serif;\n"
  188.             + "        color: #000000;\n"
  189.             + "        margin-top: 0;\n"
  190.             + "      }\n"
  191.             + "      /* What it does: Stops email clients resizing small text. */\n"
  192.             + "      * {\n"
  193.             + "        -ms-text-size-adjust: 100%;\n"
  194.             + "        -webkit-text-size-adjust: 100%;\n"
  195.             + "      }\n"
  196.             + "      /* What it does: Prevents Windows 10 Mail from underlining links despite inline CSS. Styles for underlined links should be inline. */\n"
  197.             + "      a {\n"
  198.             + "        text-decoration: none;\n"
  199.             + "      }\n"
  200.             + "      /* What it does: Removes right gutter in Gmail iOS app: https://github.com/TedGoas/Cerberus/issues/89  */\n"
  201.             + "      /* Create one of these media queries for each additional viewport size you'd like to fix */\n"
  202.             + "\n"
  203.             + "      /* iPhone 4, 4S, 5, 5S, 5C, and 5SE */\n"
  204.             + "      @media only screen and (min-device-width: 320px) and (max-device-width: 374px) {\n"
  205.             + "        u ~ div .email-container {\n"
  206.             + "          min-width: 320px !important;\n"
  207.             + "        }\n"
  208.             + "      }\n"
  209.             + "      /* iPhone 6, 6S, 7, 8, and X */\n"
  210.             + "      @media only screen and (min-device-width: 375px) and (max-device-width: 413px) {\n"
  211.             + "        u ~ div .email-container {\n"
  212.             + "          min-width: 375px !important;\n"
  213.             + "        }\n"
  214.             + "      }\n"
  215.             + "      /* iPhone 6+, 7+, and 8+ */\n"
  216.             + "      @media only screen and (min-device-width: 414px) {\n"
  217.             + "        u ~ div .email-container {\n"
  218.             + "          min-width: 414px !important;\n"
  219.             + "        }\n"
  220.             + "      }\n"
  221.             + "    </style>\n"
  222.             + "  </head>\n"
  223.             + "\n"
  224.             + "  <body\n"
  225.             + "    width=\"100%\"\n"
  226.             + "    style=\"\n"
  227.             + "      margin: 0;\n"
  228.             + "      padding: 0 !important;\n"
  229.             + "      mso-line-height-rule: exactly;\n"
  230.             + "      background-color: #f1f1f1;\n"
  231.             + "      font-family: sans-serif;\n"
  232.             + "      font-size: 15px;\n"
  233.             + "      line-height: 1.8;\n"
  234.             + "      color: rgba(0, 0, 0, 0.4);\n"
  235.             + "    \"\n"
  236.             + "  >\n"
  237.             + "    <div style=\"max-width: 600px; margin: 0 auto\" class=\"email-container\">\n"
  238.             + "      <div\n"
  239.             + "        align=\"center\"\n"
  240.             + "        role=\"presentation\"\n"
  241.             + "        cellspacing=\"0\"\n"
  242.             + "        cellpadding=\"0\"\n"
  243.             + "        border=\"0\"\n"
  244.             + "        width=\"100%\"\n"
  245.             + "        style=\"margin: auto\"\n"
  246.             + "      >\n"
  247.             + "        <div valign=\"middle\" class=\"hero\" style=\"padding: 3em 0 2em 0; background: #ffffff\">\n"
  248.             + "          " + picture + "\n"
  249.             + "          <div class=\"text\" style=\"padding: 0 2.5em; text-align: center\">\n"
  250.             + (StringUtils.isNotBlank(heading)
  251.                 ? ("            <h2 style=\"font-size: 30px; margin-bottom: 0\">" + heading
  252.                     + "</h2>\n")
  253.                 : (""))
  254.             + (StringUtils.isNotBlank(subheading) ? ("            <h3>" + subheading + "</h3>\n")
  255.                 : (""))
  256.             + (StringUtils.isNotBlank(info) ? ("            " + info + "\n")
  257.                 : (""))
  258.             + "            <p>\n"
  259.             + "              <a\n"
  260.             + "                href=\"" + linkHref + "\"\n"
  261.             + "                style=\"\n"
  262.             + "                  padding: 10px 15px;\n"
  263.             + "                  display: inline-block;\n"
  264.             + "                  border-radius: 5px;\n"
  265.             + "                  background: #50bfd5;\n"
  266.             + "                  color: #ffffff;\n"
  267.             + "                \">\n"
  268.             + "                " + linkLabel + "\n"
  269.             + "              </a>\n"
  270.             + "            </p>\n"
  271.             + ((footer != null && footer.isEmpty())
  272.                 ? ("            <p>" + footer.stream().collect(Collectors.joining(" ")) + "</p>")
  273.                 : (""))
  274.             + "          </div>\n"
  275.             + "        </div>\n"
  276.             + "      </div>\n"
  277.             + "    </div>\n"
  278.             + "  </body>\n"
  279.             + "</html>";
  280.     }

  281. }