From 95c552ee565394e1d81cccef2ca8bb433ebcd0be Mon Sep 17 00:00:00 2001
From: Grant Commodore <gcommodore@google.com>
Date: Fri, 7 Aug 2020 17:36:31 -0400
Subject: [PATCH] Fixes issue with emails not being sent  (#178)

* rfr

* removes try
---
 .../servlets/IntervieweeFeedbackServlet.java  | 18 ++----
 .../servlets/InterviewerFeedbackServlet.java  | 18 ++----
 .../servlets/ScheduledInterviewServlet.java   | 23 +++-----
 .../java/com/google/sps/utils/EmailUtils.java | 46 +++++++++++++--
 .../com/google/sps/utils/FakeEmailUtils.java  | 55 -----------------
 .../google/sps/utils/SendgridEmailUtils.java  | 59 -------------------
 .../IntervieweeFeedbackServletTest.java       |  8 +--
 .../InterviewerFeedbackServletTest.java       |  8 +--
 .../ScheduledInterviewServletTest.java        | 24 ++++----
 .../email/NewInterview_Interviewee.txt        | 20 +++++++
 .../email/NewInterview_Interviewer.txt        | 20 +++++++
 .../templates/email/NewInterview_Shadow.txt   | 11 ++++
 .../email/TechnicalQuestions_Interviewee.txt  | 31 ++++++++++
 .../email/TechnicalQuestions_Interviewer.txt  | 13 ++++
 .../templates/email/feedbackToInterviewee.txt | 25 ++++++++
 .../templates/email/feedbackToInterviewer.txt | 19 ++++++
 16 files changed, 208 insertions(+), 190 deletions(-)
 delete mode 100644 src/main/java/com/google/sps/utils/FakeEmailUtils.java
 delete mode 100644 src/main/java/com/google/sps/utils/SendgridEmailUtils.java
 create mode 100644 src/test/resources/templates/email/NewInterview_Interviewee.txt
 create mode 100644 src/test/resources/templates/email/NewInterview_Interviewer.txt
 create mode 100644 src/test/resources/templates/email/NewInterview_Shadow.txt
 create mode 100644 src/test/resources/templates/email/TechnicalQuestions_Interviewee.txt
 create mode 100644 src/test/resources/templates/email/TechnicalQuestions_Interviewer.txt
 create mode 100644 src/test/resources/templates/email/feedbackToInterviewee.txt
 create mode 100644 src/test/resources/templates/email/feedbackToInterviewer.txt

diff --git a/src/main/java/com/google/sps/servlets/IntervieweeFeedbackServlet.java b/src/main/java/com/google/sps/servlets/IntervieweeFeedbackServlet.java
index f2519ec08..42ecf509e 100644
--- a/src/main/java/com/google/sps/servlets/IntervieweeFeedbackServlet.java
+++ b/src/main/java/com/google/sps/servlets/IntervieweeFeedbackServlet.java
@@ -25,7 +25,6 @@
 import com.google.sps.data.ScheduledInterviewDao;
 import com.google.sps.data.SendgridEmailSender;
 import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.SendgridEmailUtils;
 import com.sendgrid.helpers.mail.Mail;
 import com.sendgrid.helpers.mail.objects.Content;
 import com.sendgrid.helpers.mail.objects.Email;
@@ -50,7 +49,6 @@ public class IntervieweeFeedbackServlet extends HttpServlet {
   private ScheduledInterviewDao scheduledInterviewDao;
   private PersonDao personDao;
   private EmailSender emailSender;
-  private EmailUtils emailUtils;
   static final Email sender = new Email("interviewme.business@gmail.com");
   private Path emailsPath =
       Paths.get(
@@ -64,22 +62,14 @@ public void init() {
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
-    init(
-        new DatastoreScheduledInterviewDao(),
-        new DatastorePersonDao(),
-        emailSender,
-        new SendgridEmailUtils());
+    init(new DatastoreScheduledInterviewDao(), new DatastorePersonDao(), emailSender);
   }
 
   public void init(
-      ScheduledInterviewDao scheduledInterviewDao,
-      PersonDao personDao,
-      EmailSender emailSender,
-      EmailUtils emailUtils) {
+      ScheduledInterviewDao scheduledInterviewDao, PersonDao personDao, EmailSender emailSender) {
     this.scheduledInterviewDao = scheduledInterviewDao;
     this.personDao = personDao;
     this.emailSender = emailSender;
-    this.emailUtils = emailUtils;
   }
 
   @Override
@@ -148,8 +138,8 @@ private void sendFeedback(String intervieweeEmail, HashMap<String, String> answe
     String subject = "Your Interviewer has submitted feedback for your interview!";
     Email recipient = new Email(intervieweeEmail);
     String contentString =
-        emailUtils.fileContentToString(emailsPath + "/feedbackToInterviewee.txt");
-    Content content = new Content("text/plain", emailUtils.replaceAllPairs(answers, contentString));
+        EmailUtils.fileContentToString(emailsPath + "/feedbackToInterviewee.txt");
+    Content content = new Content("text/plain", EmailUtils.replaceAllPairs(answers, contentString));
     emailSender.sendEmail(recipient, subject, content);
   }
 }
diff --git a/src/main/java/com/google/sps/servlets/InterviewerFeedbackServlet.java b/src/main/java/com/google/sps/servlets/InterviewerFeedbackServlet.java
index 280e78c38..533b218c0 100644
--- a/src/main/java/com/google/sps/servlets/InterviewerFeedbackServlet.java
+++ b/src/main/java/com/google/sps/servlets/InterviewerFeedbackServlet.java
@@ -25,7 +25,6 @@
 import com.google.sps.data.ScheduledInterviewDao;
 import com.google.sps.data.SendgridEmailSender;
 import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.SendgridEmailUtils;
 import com.sendgrid.helpers.mail.Mail;
 import com.sendgrid.helpers.mail.objects.Content;
 import com.sendgrid.helpers.mail.objects.Email;
@@ -50,7 +49,6 @@ public class InterviewerFeedbackServlet extends HttpServlet {
   private ScheduledInterviewDao scheduledInterviewDao;
   private PersonDao personDao;
   private EmailSender emailSender;
-  private EmailUtils emailUtils;
   static final Email sender = new Email("interviewme.business@gmail.com");
   private Path emailsPath =
       Paths.get(
@@ -64,22 +62,14 @@ public void init() {
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
-    init(
-        new DatastoreScheduledInterviewDao(),
-        new DatastorePersonDao(),
-        emailSender,
-        new SendgridEmailUtils());
+    init(new DatastoreScheduledInterviewDao(), new DatastorePersonDao(), emailSender);
   }
 
   public void init(
-      ScheduledInterviewDao scheduledInterviewDao,
-      PersonDao personDao,
-      EmailSender emailSender,
-      EmailUtils emailUtils) {
+      ScheduledInterviewDao scheduledInterviewDao, PersonDao personDao, EmailSender emailSender) {
     this.scheduledInterviewDao = scheduledInterviewDao;
     this.personDao = personDao;
     this.emailSender = emailSender;
-    this.emailUtils = emailUtils;
   }
 
   @Override
@@ -147,8 +137,8 @@ private void sendFeedback(String interviewerEmail, HashMap<String, String> answe
     String subject = "Your Interviewee has submitted feedback for your interview!";
     Email recipient = new Email(interviewerEmail);
     String contentString =
-        emailUtils.fileContentToString(emailsPath + "/feedbackToInterviewer.txt");
-    Content content = new Content("text/plain", emailUtils.replaceAllPairs(answers, contentString));
+        EmailUtils.fileContentToString(emailsPath + "/feedbackToInterviewer.txt");
+    Content content = new Content("text/plain", EmailUtils.replaceAllPairs(answers, contentString));
     emailSender.sendEmail(recipient, subject, content);
   }
 }
diff --git a/src/main/java/com/google/sps/servlets/ScheduledInterviewServlet.java b/src/main/java/com/google/sps/servlets/ScheduledInterviewServlet.java
index b24c6c00c..1ae5a3de7 100644
--- a/src/main/java/com/google/sps/servlets/ScheduledInterviewServlet.java
+++ b/src/main/java/com/google/sps/servlets/ScheduledInterviewServlet.java
@@ -38,7 +38,6 @@
 import com.google.sps.data.SendgridEmailSender;
 import com.google.sps.data.TimeRange;
 import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.SendgridEmailUtils;
 import com.sendgrid.Response;
 import com.sendgrid.SendGrid;
 import com.sendgrid.helpers.mail.Mail;
@@ -81,12 +80,8 @@ public class ScheduledInterviewServlet extends HttpServlet {
   private EmailSender emailSender;
   private CalendarAccess calendarAccess;
   private Calendar service;
-  private EmailUtils emailUtils;
   private final UserService userService = UserServiceFactory.getUserService();
   static final Email sender = new Email("interviewme.business@gmail.com");
-  private Path emailsPath =
-      Paths.get(
-          System.getProperty("user.home") + "/InterviewMe/src/main/resources/templates/email");
 
   @Override
   public void init() {
@@ -113,8 +108,7 @@ public void init() {
         new DatastoreAvailabilityDao(),
         new DatastorePersonDao(),
         calendar,
-        emailSender,
-        new SendgridEmailUtils());
+        emailSender);
   }
 
   public void init(
@@ -122,14 +116,12 @@ public void init(
       AvailabilityDao availabilityDao,
       PersonDao personDao,
       CalendarAccess calendarAccess,
-      EmailSender emailSender,
-      EmailUtils emailUtils) {
+      EmailSender emailSender) {
     this.scheduledInterviewDao = scheduledInterviewDao;
     this.availabilityDao = availabilityDao;
     this.personDao = personDao;
     this.calendarAccess = calendarAccess;
     this.emailSender = emailSender;
-    this.emailUtils = emailUtils;
   }
 
   // Gets the current user's email and returns the ScheduledInterviews for that person.
@@ -447,22 +439,21 @@ private void sendParticipantEmail(
     }
 
     String subject = "You have been requested to conduct a mock interview!";
-    String contentString =
-        emailUtils.fileContentToString(emailsPath + "/NewInterview_Interviewer.txt");
+    String contentString = EmailUtils.fileContentToString("NewInterview_Interviewer.txt");
 
     if (participantId.equals(scheduledInterview.intervieweeId())) {
       subject = "You have been registered for a mock interview!";
-      contentString = emailUtils.fileContentToString(emailsPath + "/NewInterview_Interviewee.txt");
+      contentString = EmailUtils.fileContentToString("NewInterview_Interviewee.txt");
     }
 
     if (participantId.equals(scheduledInterview.shadowId())) {
       subject = "You have been registered for a mock interview!";
-      contentString = emailUtils.fileContentToString(emailsPath + "/NewInterview_Shadow.txt");
+      contentString = EmailUtils.fileContentToString("NewInterview_Shadow.txt");
     }
 
     Email recipient = new Email(recipientEmail);
     Content content =
-        new Content("text/plain", emailUtils.replaceAllPairs(emailedDetails, contentString));
+        new Content("text/plain", EmailUtils.replaceAllPairs(emailedDetails, contentString));
     emailSender.sendEmail(recipient, subject, content);
   }
   // Formats the position string that is sent in an email. For example SOFTWARE_ENGINEER -> Software
@@ -471,7 +462,7 @@ private static String formatPositionString(String str) {
     String splitString[] = str.split("_", 0);
     String formattedPositionString = "";
     for (String s : splitString) {
-      formattedPositionString += s.substring(0, 1) + s.substring(1).toLowerCase();
+      formattedPositionString += s.substring(0, 1) + s.substring(1).toLowerCase() + " ";
     }
     return formattedPositionString.trim();
   }
diff --git a/src/main/java/com/google/sps/utils/EmailUtils.java b/src/main/java/com/google/sps/utils/EmailUtils.java
index 0a25e21b4..dbcaef1f3 100644
--- a/src/main/java/com/google/sps/utils/EmailUtils.java
+++ b/src/main/java/com/google/sps/utils/EmailUtils.java
@@ -14,18 +14,36 @@
 
 package com.google.sps.utils;
 
+// using SendGrid's Java Library
+// https://github.com/sendgrid/sendgrid-java
+import com.sendgrid.Method;
+import com.sendgrid.Request;
 import com.sendgrid.Response;
-import com.sendgrid.helpers.mail.objects.Content;
-import com.sendgrid.helpers.mail.objects.Email;
+import com.sendgrid.SendGrid;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+import java.util.Map;
 import java.util.HashMap;
+import java.lang.ClassLoader;
+import java.net.URI;
+import java.net.URL;
+import java.net.URISyntaxException;
 
-/** EmailUtils includes the basic methods used when formatting emails. */
-public interface EmailUtils {
+// Used to format contents of an email
+public class EmailUtils {
 
   // Returns the contents of the file specified at filePath as a String. Useful for converting
   // predefined email templates to text.
-  public String fileContentToString(String filePath) throws IOException;
+  public static String fileContentToString(String fileName) throws IOException {
+    StringBuilder contentBuilder = new StringBuilder();
+    Stream<String> stream =
+        Files.lines(Paths.get(getEmailTemplateResource(fileName)), StandardCharsets.UTF_8);
+    stream.forEach(s -> contentBuilder.append(s).append("\n"));
+    return contentBuilder.toString();
+  }
 
   /**
    * Modifies and returns @param str. Replaces all occurences in @param str of each key in @param
@@ -34,5 +52,21 @@ public interface EmailUtils {
   // Ex. str = "You will be mock interviewing {{interviewee_full_name}} on {{formatted_date}}."
   // toReplace = { ("{{interviewee_full_name}}","Tess"), ("{{formatted_date}}", "June 6, 2022") }
   // Returned: "You will be mock interviewing Tess on June 6, 2022."
-  public String replaceAllPairs(HashMap<String, String> toReplace, String str);
+  public static String replaceAllPairs(HashMap<String, String> toReplace, String str) {
+    for (Map.Entry<String, String> entry : toReplace.entrySet()) {
+      str = str.replace(entry.getKey(), entry.getValue());
+    }
+    return str;
+  }
+
+  private static URI getEmailTemplateResource(String fileName) {
+    URL resource = EmailUtils.class.getResource("/templates/email/" + fileName);
+    URI result;
+    try {
+      result = resource.toURI();
+    } catch (URISyntaxException e) {
+      throw new RuntimeException(e);
+    }
+    return result;
+  }
 }
diff --git a/src/main/java/com/google/sps/utils/FakeEmailUtils.java b/src/main/java/com/google/sps/utils/FakeEmailUtils.java
deleted file mode 100644
index 722e53831..000000000
--- a/src/main/java/com/google/sps/utils/FakeEmailUtils.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2019 Google LLC
-//
-// 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
-//
-//     https://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.sps.utils;
-
-// using SendGrid's Java Library
-// https://github.com/sendgrid/sendgrid-java
-import com.sendgrid.Method;
-import com.sendgrid.Request;
-import com.sendgrid.Response;
-import com.sendgrid.SendGrid;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.stream.Stream;
-import java.util.Map;
-import java.util.HashMap;
-
-// Used to format contents of an email
-public class FakeEmailUtils implements EmailUtils {
-
-  // Returns the contents of the file specified at filePath as a String. Useful for converting
-  // predefined email templates to text.
-  @Override
-  public String fileContentToString(String filePath) throws IOException {
-    return "";
-  }
-
-  /**
-   * Modifies and returns @param str. Replaces all occurences in @param str of each key in @param
-   * toReplace with its corresponding value.
-   */
-  // Ex. str = "You will be mock interviewing {{interviewee_full_name}} on {{formatted_date}}."
-  // toReplace = { ("{{interviewee_full_name}}","Tess"), ("{{formatted_date}}", "June 6, 2022") }
-  // Returned: "You will be mock interviewing Tess on June 6, 2022."
-  @Override
-  public String replaceAllPairs(HashMap<String, String> toReplace, String str) {
-    for (Map.Entry<String, String> entry : toReplace.entrySet()) {
-      str = str.replace(entry.getKey(), entry.getValue());
-    }
-    return str;
-  }
-}
diff --git a/src/main/java/com/google/sps/utils/SendgridEmailUtils.java b/src/main/java/com/google/sps/utils/SendgridEmailUtils.java
deleted file mode 100644
index 58b382ea6..000000000
--- a/src/main/java/com/google/sps/utils/SendgridEmailUtils.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2019 Google LLC
-//
-// 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
-//
-//     https://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.sps.utils;
-
-// using SendGrid's Java Library
-// https://github.com/sendgrid/sendgrid-java
-import com.sendgrid.Method;
-import com.sendgrid.Request;
-import com.sendgrid.Response;
-import com.sendgrid.SendGrid;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.stream.Stream;
-import java.util.Map;
-import java.util.HashMap;
-
-// Used to format contents of an email
-public class SendgridEmailUtils implements EmailUtils {
-
-  // Returns the contents of the file specified at filePath as a String. Useful for converting
-  // predefined email templates to text.
-  @Override
-  public String fileContentToString(String filePath) throws IOException {
-    StringBuilder contentBuilder = new StringBuilder();
-    try (Stream<String> stream = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)) {
-      stream.forEach(s -> contentBuilder.append(s).append("\n"));
-    }
-    return contentBuilder.toString();
-  }
-
-  /**
-   * Modifies and returns @param str. Replaces all occurences in @param str of each key in @param
-   * toReplace with its corresponding value.
-   */
-  // Ex. str = "You will be mock interviewing {{interviewee_full_name}} on {{formatted_date}}."
-  // toReplace = { ("{{interviewee_full_name}}","Tess"), ("{{formatted_date}}", "June 6, 2022") }
-  // Returned: "You will be mock interviewing Tess on June 6, 2022."
-  @Override
-  public String replaceAllPairs(HashMap<String, String> toReplace, String str) {
-    for (Map.Entry<String, String> entry : toReplace.entrySet()) {
-      str = str.replace(entry.getKey(), entry.getValue());
-    }
-    return str;
-  }
-}
diff --git a/src/test/java/com/google/sps/servlets/IntervieweeFeedbackServletTest.java b/src/test/java/com/google/sps/servlets/IntervieweeFeedbackServletTest.java
index 86922d2ac..258c49836 100644
--- a/src/test/java/com/google/sps/servlets/IntervieweeFeedbackServletTest.java
+++ b/src/test/java/com/google/sps/servlets/IntervieweeFeedbackServletTest.java
@@ -31,8 +31,6 @@
 import com.google.sps.data.Job;
 import com.google.sps.data.ScheduledInterview;
 import com.google.sps.data.TimeRange;
-import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.FakeEmailUtils;
 import com.google.sps.servlets.IntervieweeFeedbackServlet;
 import com.sendgrid.helpers.mail.objects.Email;
 import java.io.IOException;
@@ -59,7 +57,6 @@ public final class IntervieweeFeedbackServletTest {
   private FakeScheduledInterviewDao scheduledInterviewDao;
   private FakePersonDao personDao;
   private FakeEmailSender emailSender;
-  private FakeEmailUtils emailUtils;
   private final ScheduledInterview scheduledInterview =
       ScheduledInterview.create(
           /*id=*/ (long) -1,
@@ -81,7 +78,6 @@ public void setUp() {
     }
     scheduledInterviewDao = new FakeScheduledInterviewDao();
     personDao = new FakePersonDao();
-    emailUtils = new FakeEmailUtils();
   }
 
   @After
@@ -93,7 +89,7 @@ public void tearDown() {
   @Test
   public void interviewIdDoesNotExist() throws IOException {
     IntervieweeFeedbackServlet intervieweeFeedbackServlet = new IntervieweeFeedbackServlet();
-    intervieweeFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender, emailUtils);
+    intervieweeFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender);
     scheduledInterviewDao.create(scheduledInterview);
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -109,7 +105,7 @@ public void interviewIdDoesNotExist() throws IOException {
   public void invalidUser() throws IOException {
     IntervieweeFeedbackServlet intervieweeFeedbackServlet = new IntervieweeFeedbackServlet();
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@mail.com").setEnvAuthDomain("auth");
-    intervieweeFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender, emailUtils);
+    intervieweeFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender);
     scheduledInterviewDao.create(scheduledInterview);
     List<ScheduledInterview> scheduledInterviews =
         scheduledInterviewDao.getForPerson(emailToId("user@mail.com"));
diff --git a/src/test/java/com/google/sps/servlets/InterviewerFeedbackServletTest.java b/src/test/java/com/google/sps/servlets/InterviewerFeedbackServletTest.java
index 0bf797e1a..b202bc253 100644
--- a/src/test/java/com/google/sps/servlets/InterviewerFeedbackServletTest.java
+++ b/src/test/java/com/google/sps/servlets/InterviewerFeedbackServletTest.java
@@ -31,8 +31,6 @@
 import com.google.sps.data.Job;
 import com.google.sps.data.ScheduledInterview;
 import com.google.sps.data.TimeRange;
-import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.FakeEmailUtils;
 import com.google.sps.servlets.InterviewerFeedbackServlet;
 import com.sendgrid.helpers.mail.objects.Email;
 import java.io.IOException;
@@ -59,7 +57,6 @@ public final class InterviewerFeedbackServletTest {
   private FakeScheduledInterviewDao scheduledInterviewDao;
   private FakePersonDao personDao;
   private FakeEmailSender emailSender;
-  private FakeEmailUtils emailUtils;
   private final ScheduledInterview scheduledInterview =
       ScheduledInterview.create(
           /*id=*/ (long) -1,
@@ -81,7 +78,6 @@ public void setUp() {
     }
     scheduledInterviewDao = new FakeScheduledInterviewDao();
     personDao = new FakePersonDao();
-    emailUtils = new FakeEmailUtils();
   }
 
   @After
@@ -94,7 +90,7 @@ public void tearDown() {
   public void interviewIdDoesNotExist() throws IOException {
     InterviewerFeedbackServlet interviewerFeedbackServlet = new InterviewerFeedbackServlet();
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
-    interviewerFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender, emailUtils);
+    interviewerFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender);
     scheduledInterviewDao.create(scheduledInterview);
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -109,7 +105,7 @@ public void interviewIdDoesNotExist() throws IOException {
   public void invalidUser() throws IOException {
     InterviewerFeedbackServlet interviewerFeedbackServlet = new InterviewerFeedbackServlet();
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
-    interviewerFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender, emailUtils);
+    interviewerFeedbackServlet.init(scheduledInterviewDao, personDao, emailSender);
     scheduledInterviewDao.create(scheduledInterview);
     List<ScheduledInterview> scheduledInterviews =
         scheduledInterviewDao.getForPerson(emailToId("user@company.org"));
diff --git a/src/test/java/com/google/sps/servlets/ScheduledInterviewServletTest.java b/src/test/java/com/google/sps/servlets/ScheduledInterviewServletTest.java
index 9fdd85062..2937fcfd4 100644
--- a/src/test/java/com/google/sps/servlets/ScheduledInterviewServletTest.java
+++ b/src/test/java/com/google/sps/servlets/ScheduledInterviewServletTest.java
@@ -33,8 +33,6 @@
 import com.google.sps.data.ScheduledInterview;
 import com.google.sps.data.ScheduledInterviewRequest;
 import com.google.sps.data.TimeRange;
-import com.google.sps.utils.EmailUtils;
-import com.google.sps.utils.FakeEmailUtils;
 import com.google.gson.reflect.TypeToken;
 import com.google.sps.data.Job;
 import com.google.sps.data.Person;
@@ -70,7 +68,6 @@ public final class ScheduledInterviewServletTest {
   private FakePersonDao personDao;
   private FakeCalendarAccess calendarAccess;
   private FakeEmailSender emailSender;
-  private FakeEmailUtils emailUtils;
 
   private final Person googleSWE1 =
       Person.create(
@@ -215,7 +212,6 @@ public void setUp() {
     availabilityDao = new FakeAvailabilityDao();
     personDao = new FakePersonDao();
     calendarAccess = new FakeCalendarAccess();
-    emailUtils = new FakeEmailUtils();
   }
 
   @After
@@ -228,7 +224,7 @@ public void tearDown() {
   public void returnsScheduledInterviewsForUser() throws IOException {
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail(googleSWE1.email()).setEnvAuthDomain("auth");
     MockHttpServletRequest getRequest = new MockHttpServletRequest();
     MockHttpServletResponse getResponse = new MockHttpServletResponse();
@@ -282,7 +278,7 @@ public void returnsScheduledInterviewsForUser() throws IOException {
   public void returnsScheduledInterviewsInOrder() throws IOException {
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail(googleSWE1.email()).setEnvAuthDomain("auth");
     MockHttpServletRequest getRequest = new MockHttpServletRequest();
     MockHttpServletResponse getResponse = new MockHttpServletResponse();
@@ -358,7 +354,7 @@ public void onlyReturnsInterviewersWithMatchingCompanyAndJob() throws IOExceptio
     availabilityDao.create(googlePMAvail4);
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -399,7 +395,7 @@ public void picksOneOfThePossibleInterviewers() throws IOException {
     availabilityDao.create(googleSWE2QualPMInterviewerAvail4);
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -455,7 +451,7 @@ public void availabilitiesAreScheduled() throws IOException {
 
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -490,7 +486,7 @@ public void availabilitiesAreScheduled() throws IOException {
   public void invalidInstant() throws IOException {
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -507,7 +503,7 @@ public void invalidInstant() throws IOException {
   public void getShadowName() throws IOException {
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail(googleSWE1.email()).setEnvAuthDomain("auth");
     MockHttpServletRequest getRequest = new MockHttpServletRequest();
     MockHttpServletResponse getResponse = new MockHttpServletResponse();
@@ -550,7 +546,7 @@ public void getShadowName() throws IOException {
   public void noShadow() throws IOException {
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail(googleSWE1.email()).setEnvAuthDomain("auth");
     MockHttpServletRequest getRequest = new MockHttpServletRequest();
     MockHttpServletResponse getResponse = new MockHttpServletResponse();
@@ -606,7 +602,7 @@ public void onlySchedulesWithQualifiedInterviewers() throws IOException {
     availabilityDao.create(googleSWE2QualPMInterviewerAvail4);
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail("user@company.org").setEnvAuthDomain("auth");
     MockHttpServletRequest postRequest = new MockHttpServletRequest();
     MockHttpServletResponse postResponse = new MockHttpServletResponse();
@@ -695,7 +691,7 @@ public void shadowIsAddedToAViableInterview() throws IOException {
 
     ScheduledInterviewServlet scheduledInterviewServlet = new ScheduledInterviewServlet();
     scheduledInterviewServlet.init(
-        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender, emailUtils);
+        scheduledInterviewDao, availabilityDao, personDao, calendarAccess, emailSender);
     helper.setEnvIsLoggedIn(true).setEnvEmail(shadow.email()).setEnvAuthDomain("auth");
     MockHttpServletRequest putRequest = new MockHttpServletRequest();
     MockHttpServletResponse putResponse = new MockHttpServletResponse();
diff --git a/src/test/resources/templates/email/NewInterview_Interviewee.txt b/src/test/resources/templates/email/NewInterview_Interviewee.txt
new file mode 100644
index 000000000..b3c94fbe0
--- /dev/null
+++ b/src/test/resources/templates/email/NewInterview_Interviewee.txt
@@ -0,0 +1,20 @@
+Hello {{interviewee_first_name}},
+
+You have been registered for a mock interview on {{formatted_date}}. You are the interviewee. You will be interviewed by {{interviewer_first_name}} for the position of: {{position}}.
+
+Before the interview, you will need to:
+  - Prepare your resume to share with your interviewer if they ask for it.
+  - Reflect and/or study up on how a real life interview for a {{position}} position would go. Prepare for this as you would for a real interview.
+  - Prepare the appropriate interview attire for a {{position}} interview. 
+
+Be sure to follow these general guidelines when interviewing:
+  - Be respectful to the interviewer. They are volunteering their time to help you.
+  - Treat this as an actual interview. This is how you will get the most out of your InterviewMe experience.
+
+After interviewing:
+ - Your interviewer will write up a feedback report. Expect to see this in your inbox shortly.
+ - Send the interviewer feedback through this form: {{form_link}}.
+
+Your interview will be conducted in this Google Virtual Chat: {{chat_link}}.
+
+Please reach out to interviewme.business@gmail.com if you have any questions. 
diff --git a/src/test/resources/templates/email/NewInterview_Interviewer.txt b/src/test/resources/templates/email/NewInterview_Interviewer.txt
new file mode 100644
index 000000000..010850f21
--- /dev/null
+++ b/src/test/resources/templates/email/NewInterview_Interviewer.txt
@@ -0,0 +1,20 @@
+Hello {{interviewer_first_name}},
+
+You have been registered for a mock interview on {{formatted_date}}. You are the interviewer. You will be interviewing {{interviewee_first_name}} for the position of: {{position}}.
+
+Before the interview, you will need to:
+  - Think about the distribution of questions you need. How many technical questions? How many behavioral questions? Prepare more than enough.
+  - Reflect and/or study up on how a real life interview for a {{position}} position would go. Try to model the mock interview after a real one.
+  - Prepare the appropriate interview attire for a {{position}} interview.   
+
+Be sure to follow these general guidelines when interviewing:
+  - Keep the time in mind. The interview lasts an hour, but leave about 15 minutes at the end to give your interviewee feedback. Note that this post-interview feedback is something done in a mock interview but not a real life interview.
+  - Treat this as an actual interview. This is how you will get the most out of your InterviewMe experience.
+  
+After interviewing:
+ - Your interviewee will write up a feedback report. Expect to see this in your inbox shortly.
+ - Send the interviewee feedback through this form: {{form_link}}.
+
+Your interview will be conducted in this Google Virtual Chat: {{chat_link}}.
+
+Please reach out to interviewme.business@gmail.com if you have any questions. 
diff --git a/src/test/resources/templates/email/NewInterview_Shadow.txt b/src/test/resources/templates/email/NewInterview_Shadow.txt
new file mode 100644
index 000000000..5bec3ae41
--- /dev/null
+++ b/src/test/resources/templates/email/NewInterview_Shadow.txt
@@ -0,0 +1,11 @@
+Hello {{shadow_first_name}},
+
+You have been registered for a mock interview on {{formatted_date}}. You are the shadow. You will be shadowing an interview for the position of: {{position}}.
+
+Be sure to follow these general guidelines when shadowing:
+  - Be respectful to the interviewer and interviewee.
+  - Please mute yourself. You are here to observe. 
+
+The interview will be conducted in this Google Virtual Chat: {{chat_link}}.
+
+Please reach out to interviewme.business@gmail.com if you have any questions. 
diff --git a/src/test/resources/templates/email/TechnicalQuestions_Interviewee.txt b/src/test/resources/templates/email/TechnicalQuestions_Interviewee.txt
new file mode 100644
index 000000000..92822dce6
--- /dev/null
+++ b/src/test/resources/templates/email/TechnicalQuestions_Interviewee.txt
@@ -0,0 +1,31 @@
+Hello {{interviewee_first_name}},
+
+We see that you registered for a {{position}} mock interview with InterviewMe on {{formatted_date}}. As these interviews usually come with technical questions, we wanted to share with you some tips.
+
+  Repeat/clarify the question with the interviewer.
+    - Pay attention for hints.
+    - Vagueness is expected. This gives you the chance to define the problem better.
+
+  Brainstorm potential solutions.
+    - Start with the obvious/worst case.
+    - Draw pictures.
+    - Evaluate potential solutions by running time.
+    - Remember, this is a conversation, not a monologue.
+
+  Before coding:
+    - Make sure you understand your approach.
+    - Make sure the interviewer understands your approach.
+    - You may want to pick a suboptimal approach if it's easier to code (although often the optimal approach is the simplest.)
+    - Think about APIs, function signatures, etc.
+
+  During coding:
+    - Small syntax/language issues are OK, but avoid pseudo-code.
+    - Subroutines can help clarify code/allow you to skip writing some code.
+    - Style counts; use semantically meaningful names.
+
+  After coding:
+    - Talk about testing and test cases in general.
+    - Finally, talk about other possibly more efficient solutions with the interviewer.
+
+Please reach out to interviewme.business@gmail.com if you have any questions.   
+Best of luck!
diff --git a/src/test/resources/templates/email/TechnicalQuestions_Interviewer.txt b/src/test/resources/templates/email/TechnicalQuestions_Interviewer.txt
new file mode 100644
index 000000000..bac06ace0
--- /dev/null
+++ b/src/test/resources/templates/email/TechnicalQuestions_Interviewer.txt
@@ -0,0 +1,13 @@
+Hello {{interviewer_first_name}},
+
+We see that you will be giving a {{position}} mock interview with InterviewMe on {{formatted_date}}. These interviews usually come with technical questions, which you should use to measure the candidate's competency. We wanted to share with you some tips on handling this technical portion.
+
+  - Leave some vagueness in the question. This gives the candidate the opportunity to ask clarifying questions.
+  - Does the candidate have the right approach in mind? Or will it lead them in the wrong direction? If you feel they are on the wrong track, provide a hint that will bring them in the right direction.
+  - Does the candidate make progress through the question? If they haven't been progressing, maybe it's time for a hint. 
+  - Remember, this is a conversation, not a monologue.
+  - If the candidate doesn't do so, prompt them to consider run times of proposed solutions.
+  - Finally, talk about other possibly more efficient solutions with the interviewee.
+
+Please reach out to interviewme.business@gmail.com if you have any questions.   
+Best of luck!
diff --git a/src/test/resources/templates/email/feedbackToInterviewee.txt b/src/test/resources/templates/email/feedbackToInterviewee.txt
new file mode 100644
index 000000000..e4a067658
--- /dev/null
+++ b/src/test/resources/templates/email/feedbackToInterviewee.txt
@@ -0,0 +1,25 @@
+Thank you for practicing your interviewing skills using InterviewMe on {{formatted_date}}. Your interviewer has submitted feedback for your interview, which you can view below. 
+
+The interviewee communicated their thought process as they went along: {{question_1}}
+The interviewee understood the time complexity of their solution: {{question_2}}
+The interviewee took the time to consider better solutions: {{question_3}}
+The interviewee came up with an example that they used to test their solution: {{question_4}}
+The interviewee listed a handful of edge cases and accounted for their behaviour: {{question_5}}
+The interviewee asked clarifying questions: {{question_6}}
+This InterviewMe experience was helpful: {{question_7}}
+
+What is the interviewee's strongest skill?
+{{question_8}}
+
+What is one skill they should work on improving in order to become a better candidate?
+{{question_9}}
+
+Evaluate this candidate's solution (Keep to three sentences or less):
+{{question_10}}
+
+Notes:
+{{question_11}}
+
+
+Please reach out to interviewme.business@gmail.com if you have any questions or concerns. 
+Thank you for using InterviewMe!
\ No newline at end of file
diff --git a/src/test/resources/templates/email/feedbackToInterviewer.txt b/src/test/resources/templates/email/feedbackToInterviewer.txt
new file mode 100644
index 000000000..5c984920f
--- /dev/null
+++ b/src/test/resources/templates/email/feedbackToInterviewer.txt
@@ -0,0 +1,19 @@
+Thank you for practicing your interviewing skills using InterviewMe on {{formatted_date}}. Your interviewee has submitted feedback for your interview, which you can view below. 
+
+I was comfortable during the interview: {{question_1}}
+My interviewer moved at a decent pace: {{question_2}}
+My interviewer was able to stay on topic: {{question_3}}
+My interviewer was able to provide advice or suggestions along the way when I got stuck: {{question_4}}
+My interviewer answered my questions to the best of their ability: {{question_5}}
+I felt my interviewer came prepared: {{question_6}}
+This InterviewMe experience was helpful: {{question_7}}
+
+Is there anything in particular that your interviewer did to improve your overall experience?
+{{question_8}}
+
+What is something that you think your interviewer could have done better?
+{{question_9}}
+
+
+Please reach out to interviewme.business@gmail.com if you have any questions or concerns. 
+Thank you for using InterviewMe!
\ No newline at end of file