From 30292c28c1f3079c391ab91c540bcfa008d6669c Mon Sep 17 00:00:00 2001
From: Caner <s86215@bht-berlin.de>
Date: Fri, 30 Jun 2023 23:35:55 +0200
Subject: [PATCH] nodemailer setup

---
 app/api/email/route.ts        | 51 ++++++++++++++++++++++++++++
 components/user-auth-form.tsx | 26 +++++++++++++++
 lib/auth.ts                   |  4 +++
 lib/config/nodemailer.ts      | 62 +++++++++++++++++++++++++++++++++++
 package-lock.json             | 19 +++++++++++
 package.json                  |  4 ++-
 6 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 app/api/email/route.ts
 create mode 100644 lib/config/nodemailer.ts

diff --git a/app/api/email/route.ts b/app/api/email/route.ts
new file mode 100644
index 0000000..db67cc8
--- /dev/null
+++ b/app/api/email/route.ts
@@ -0,0 +1,51 @@
+import type { NextApiRequest, NextApiResponse } from 'next';
+import * as nodemailer from 'nodemailer';
+
+// Nodemailer docs: // https://nodemailer.com/about/
+export default async function handler(
+  req: NextApiRequest,
+  res: NextApiResponse
+) {
+  // https://nodemailer.com/smtp/
+  const transporter = nodemailer.createTransport({
+    service: "gmail",
+    auth: {
+      user: process.env.NODEMAIL_MAIL,
+      pass: process.env.NODEMAIL_PW,
+    },
+    secure: false, // Default value but showing for explicitness
+  });
+
+  const { subject, email, html } = req.body;
+
+  if (!subject || !email || !html) {
+    return res
+      .status(400)
+      .json({ message: 'Please fill out the necessary fields' });
+  }
+
+  // https://nodemailer.com/message/#common-fields
+  const mailData = {
+    from: email,
+    to: email,
+    subject: `${subject}`,
+    text: `${subject} | Sent from: ${email}`,
+    html: `${html}`,
+  };
+
+  await new Promise((resolve, reject) => {
+    transporter.sendMail(mailData, (err: Error | null, info) => {
+      if (err) {
+        reject(err);
+        return res
+          .status(500)
+          .json({ error: err.message || 'Something went wrong' });
+      } else {
+        resolve(info.accepted);
+        res.status(200).json({ message: 'Message sent!' });
+      }
+    });
+  });
+
+  return;
+}
\ No newline at end of file
diff --git a/components/user-auth-form.tsx b/components/user-auth-form.tsx
index f956d48..4101b47 100644
--- a/components/user-auth-form.tsx
+++ b/components/user-auth-form.tsx
@@ -95,6 +95,32 @@ export function UserAuthForm({ type, className, ...props }: UserAuthFormProps) {
                 action: <ToastAction altText="Try again">Try again</ToastAction>,
             })
         }
+        try {
+            const res = await fetch('/api/email', {
+                method: 'POST',
+                headers: {
+                    'Content-Type': 'application/json',
+                },
+                body: JSON.stringify( 
+                    subject: "Test",
+                    email: data.email,
+                    
+
+                ),
+            });
+
+            const body = await res.json();
+
+            if (res.ok) {
+                alert(`${body.message} 🚀`);
+            }
+
+            if (res.status === 400) {
+                alert(`${body.message} 😢`);
+            }
+        } catch (err) {
+            console.log('Something went wrong: ', err);
+        }
 
         router.push("/home")
 
diff --git a/lib/auth.ts b/lib/auth.ts
index b1696bb..6834734 100644
--- a/lib/auth.ts
+++ b/lib/auth.ts
@@ -55,6 +55,10 @@ export const authOptions: NextAuthOptions = {
                     throw new Error('invalid password')
                 }
 
+                if(!user.emailVerified){
+                    throw new Error('email not verifyed')
+                }
+
                 return {
                     id: user.id,
                     username: user.username,
diff --git a/lib/config/nodemailer.ts b/lib/config/nodemailer.ts
new file mode 100644
index 0000000..7ec015f
--- /dev/null
+++ b/lib/config/nodemailer.ts
@@ -0,0 +1,62 @@
+
+import * as nodemailer from "nodemailer";
+import { MailOptions } from "nodemailer/lib/json-transport";
+
+export class Emailer {
+  private readonly transporter: nodemailer.Transporter;
+
+  constructor() {
+    this.transporter = nodemailer.createTransport({
+      service: "gmail",
+      auth: {
+        user: process.env.NODEMAIL_MAIL,
+        pass: process.env.NODEMAIL_PW,
+      },
+    });
+  }
+
+  public sendEmail(mailOptions: MailOptions) {
+    return this.transporter.sendMail(mailOptions);
+  }
+
+  public notifyAdminForNewUser(email: string, username: string) {
+    this.sendEmail(notifyAdminNewUserEmailTemplate(email, username));
+  }
+
+  public notifyUserForSignup(email: string, username: string) {
+    this.sendEmail(newUserEmailTemplate(email, username));
+  }
+}
+
+export const emailer = new Emailer();
+
+export const newUserEmailTemplate = (email: string, username: string) => {
+  return {
+    from: process.env.GMAIL_USER,
+    to: email,
+    subject: `${username}, Welcome to the our website`,
+    text: "Welcome to the our website",
+    html: `
+      <h1>Welcome to our website!</h1>
+      <p>We're glad you've decided to join us. We hope you find everything you're looking for here and enjoy using our site.</p>
+      <p>If you have any questions or need any help, please don't hesitate to contact us. Thank you for signing up!</p>
+    `,
+  } as MailOptions;
+};
+
+export const notifyAdminNewUserEmailTemplate = (
+  email: string,
+  username: string
+) => {
+  return {
+    from: process.env.GMAIL_USER,
+    to: process.env.GMAIL_USER,
+    subject: `New User: ${username} - email: ${email}`,
+    text: `New User: ${username} - email: ${email}`,
+    html: `
+      <h1>New User: ${username}</h1>
+      <p>email: ${email}</p>
+    `,
+  } as MailOptions;
+};
+
diff --git a/package-lock.json b/package-lock.json
index cc3d3ed..0e5e3d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,6 +33,7 @@
         "next": "^13.4.7",
         "next-auth": "^4.22.1",
         "next-themes": "^0.2.1",
+        "nodemailer": "^6.9.3",
         "normalize-diacritics": "^4.0.0",
         "react": "18.2.0",
         "react-dom": "18.2.0",
@@ -52,6 +53,7 @@
         "@types/bcrypt": "^5.0.0",
         "@types/jest": "^29.5.2",
         "@types/node": "^20.3.2",
+        "@types/nodemailer": "^6.4.8",
         "@types/react": "^18.2.14",
         "@types/react-dom": "^18.2.6",
         "autoprefixer": "10.4.14",
@@ -2859,6 +2861,15 @@
       "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==",
       "dev": true
     },
+    "node_modules/@types/nodemailer": {
+      "version": "6.4.8",
+      "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz",
+      "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/prettier": {
       "version": "2.7.3",
       "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
@@ -8087,6 +8098,14 @@
       "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==",
       "dev": true
     },
+    "node_modules/nodemailer": {
+      "version": "6.9.3",
+      "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz",
+      "integrity": "sha512-fy9v3NgTzBngrMFkDsKEj0r02U7jm6XfC3b52eoNV+GCrGj+s8pt5OqhiJdWKuw51zCTdiNR/IUD1z33LIIGpg==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
     "node_modules/nopt": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
diff --git a/package.json b/package.json
index f87a373..277e19b 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
     "next": "^13.4.7",
     "next-auth": "^4.22.1",
     "next-themes": "^0.2.1",
+    "nodemailer": "^6.9.3",
     "normalize-diacritics": "^4.0.0",
     "react": "18.2.0",
     "react-dom": "18.2.0",
@@ -58,6 +59,7 @@
     "@types/bcrypt": "^5.0.0",
     "@types/jest": "^29.5.2",
     "@types/node": "^20.3.2",
+    "@types/nodemailer": "^6.4.8",
     "@types/react": "^18.2.14",
     "@types/react-dom": "^18.2.6",
     "autoprefixer": "10.4.14",
@@ -70,4 +72,4 @@
     "tailwindcss": "3.3.2",
     "typescript": "^5.1.6"
   }
-}
\ No newline at end of file
+}
-- 
GitLab