<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ OAuth2 - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ OAuth2 - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sat, 23 May 2026 22:20:26 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/oauth2/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ OAuth 2.0 Course for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ OAuth 2.0 is an industry-standard authorization framework that allows third-party apps access user data on another service (like Google or Facebook) without sharing passwords. Instead, it uses temporary, limited-scope access tokens for delegated acce... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/oauth-2-course-for-beginners/</link>
                <guid isPermaLink="false">695d42043e4222528514d287</guid>
                
                    <category>
                        <![CDATA[ OAuth2 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 06 Jan 2026 17:10:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767719400244/396c143c-d21a-409a-b315-6b58d120b44c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>OAuth 2.0 is an industry-standard authorization framework that allows third-party apps access user data on another service (like Google or Facebook) without sharing passwords. Instead, it uses temporary, limited-scope access tokens for delegated access, enhancing security and privacy by restricting permissions.</p>
<p>We just posted a course on the freeCodeCamp.org YouTube channel that will give you an introduction to OAuth 2.0.</p>
<p>Here are the sections in this course:</p>
<ul>
<li><p>Introduction to OAuth 2.0</p>
</li>
<li><p>OAuth 2.0 in Simple Terms: The Valet Key System</p>
</li>
<li><p>The Four OAuth Roles (Resource Owner, Client, Auth Server, Resource Server)</p>
</li>
<li><p>Why PKCE (Proof Key for Code Exchange) Matters</p>
</li>
<li><p>Project Setup &amp; Folder Structure</p>
</li>
<li><p>Building the Authorization Server</p>
</li>
<li><p>Authorization Server: Code Imports &amp; Initial Setup</p>
</li>
<li><p>Building the Resource Server (API)</p>
</li>
<li><p>Building the Client App (Authorization Code + PKCE)</p>
</li>
<li><p>Running the Full System (Auth, Resource, Client Servers)</p>
</li>
<li><p>Debugging and Fixing the JWKS Error</p>
</li>
<li><p>Debugging and Fixing the Axios 400 Error</p>
</li>
<li><p>Summary of Key Roles and Best Practices</p>
</li>
<li><p>Setting up the GitHub Repository</p>
</li>
</ul>
<p>Watch the full course on the freeCodeCamp.org YouTube channel (2-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/WSsOXo07LeE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Send Email Function using Nodemailer and OAuth2 ]]>
                </title>
                <description>
                    <![CDATA[ Being able to communicate by sending emails through web applications is important these days. It helps businesses stay connected with their potential customers. In this article, you’ll learn how to implement the Send Email function in your web app us... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/create-a-send-email-function-using-nodemailer-and-oauth2/</link>
                <guid isPermaLink="false">67e1ec8917e7e6a0f12cddf5</guid>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ nodemailer ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Chakra-ui ]]>
                    </category>
                
                    <category>
                        <![CDATA[ OAuth2 ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Okoro Emmanuel Nzube ]]>
                </dc:creator>
                <pubDate>Mon, 24 Mar 2025 23:36:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742859346889/dad1b775-f088-4c24-b252-3d85ec9e0bb7.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Being able to communicate by sending emails through web applications is important these days. It helps businesses stay connected with their potential customers.</p>
<p>In this article, you’ll learn how to implement the Send Email function in your web app using Nodemailer.</p>
<p>Let’s dive right in.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-we%E2%80%99ll-be-using">Tools We’ll Be Using</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-frontend-setup">Frontend Setup</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-install-node.js">Install Node.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-contact-form-setup">Contact Form Setup</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-backend-setup">Backend Setup</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-backend-libraries-setup">Backend Libraries Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-oauth2-configuration-setup">OAuth2 Configuration Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-nodemailer-setup">Nodemailer Setup</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>To get the absolute most out of this project, it’s important to have some basic knowledge of the following:</p>
<ul>
<li><p>JavaScript: Having a good fundamental understanding of how JS works will make it easier to follow along with the project.</p>
</li>
<li><p>React.js and Chakra UI: You should have a good understanding of how <code>usestate</code> works and how you can apply it in a project. It’s also important that you’re familiar with Chakra Ui and know how to use it to style your web application.</p>
</li>
<li><p>A little background on <a target="_blank" href="https://www.nodemailer.com/about/">Nodemailer</a> would be helpful as well.</p>
</li>
</ul>
<h2 id="heading-tools-well-be-using"><strong>Tools We’ll Be Using</strong></h2>
<p>In one of my recent projects, I created a mailer function in Node.js using Nodemailer. This function ensured that users’ emails would be delivered efficiently. And now that I know how it works, I wanted to share it with you all.</p>
<h3 id="heading-nodemailer-and-smtp">Nodemailer and SMTP</h3>
<p>So what is Nodemailer?</p>
<p>Nodemailer is a popular Node.js module that lets you send emails efficiently using different methods such as SMTP (Simple Mail Transfer Protocol), OAuth2, and so on.</p>
<p>SMTP acts like a postal service – or rather, it’s a postal service that sorts your emails and routes your messages on different mail servers until they reach their final destination. This helps ensure that your messages reach the right inbox all the time.</p>
<p>But it’s important to note that SMTP only handles the <strong>sending of emails,</strong> meaning that it doesn’t handle retrieval of already sent emails. But protocols like IMAP (Internet Message Access Protocol) and POP3 (Post Office Protocol version 3) let you retrieve emails. We won’t be using these tools here, but I just wanted you to be aware of them in case you want to implement retrieval functionality in your own projects.</p>
<h3 id="heading-oauth2">OAuth2</h3>
<p>OAuth2, short for Open Authorization, simplifies the process of authentication and authorization. With OAuth2, users don’t have to go through the hassle of repeatedly signing in or logging in. Instead, web applications can securely access private user data from other websites—only with the user's permission.</p>
<p>But don’t worry, OAuth2 only grants requesting applications limited access, typically just enough to create a basic profile. Chances are, you’ve already used OAuth2 without even realizing what’s happening behind the scenes. Pretty cool, right?</p>
<p>Now that you know a bit more about the tools we’ll be using, let’s move on.</p>
<h2 id="heading-frontend-setup">Frontend Setup</h2>
<p>First things first, you have to set up your environment. When setting up my environment, I used React.js and Chakra UI (for my styling).</p>
<h3 id="heading-install-nodejs">Install Node.js</h3>
<p>Before starting this process, make that Node is installed on your computer. If it’s not, head to their <a target="_blank" href="https://nodejs.org/en">website</a> to download and install it from there.</p>
<p>You can also use your command line to install Node by running the command <code>nvm install –lts</code>.</p>
<p>Or you could use the newest method recommended on the Node.js website, which is simply to run <code>fnm</code>.</p>
<p>Here is how you can go about it: on your command line, run the following commands:</p>
<pre><code class="lang-javascript">winget install Schniz.fnm <span class="hljs-comment">// this command downloads and installs fnm into your operating system.</span>

fnm install <span class="hljs-number">22</span> <span class="hljs-comment">// this downloads and installs node.js.</span>

node -v <span class="hljs-comment">// this displays the version of node.js currently installed in your operating system.</span>

npm – v <span class="hljs-comment">// this verifies the version of npm currently installed.</span>
</code></pre>
<p>Next, let’s set up your frontend interface.</p>
<h3 id="heading-contact-form-setup">Contact Form Setup</h3>
<p>As I mentioned above, I’m using React for my front-end and Chakra UI for styling. I won’t be going over how to install React here, but if you need help with that for your project, <a target="_blank" href="https://www.freecodecamp.org/news/how-to-install-react-a-step-by-step-guide">check out my article on it</a>.</p>
<p>Next, make sure you have Chakra UI set up. You can do this by following the steps on the <a target="_blank" href="https://chakra-ui.com/docs/get-started/frameworks/vite">Chakra Ui official website</a>.</p>
<p>Note: The web application is a full web application, which consists of various pages like Home, Services, Pricing, Contact, and so on. But for the sake of this article, we’ll focus on only the contact page.</p>
<p>Here is what the contact page will look like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477133862/421baf80-c55a-443a-9e68-c2b2e2a9b1a2.png" alt="Frontend Design interface of the Contact Form" class="image--center mx-auto" width="1603" height="831" loading="lazy"></p>
<p>The first step in building this contact form is to create your form input. Here is how you can do that:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { Box, Button, Flex, Image, Input, Text, Textarea } <span class="hljs-keyword">from</span> <span class="hljs-string">'@chakra-ui/react'</span>;
 <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Flex</span>
      <span class="hljs-attr">flexDir</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">lg:</span> '<span class="hljs-attr">row</span>', <span class="hljs-attr">md:</span> '<span class="hljs-attr">row</span>', <span class="hljs-attr">sm:</span> '<span class="hljs-attr">column</span>', <span class="hljs-attr">base:</span> '<span class="hljs-attr">column</span>' }}
      <span class="hljs-attr">pt</span>=<span class="hljs-string">"10%"</span>
      <span class="hljs-attr">w</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">lg:</span> '<span class="hljs-attr">80</span>%' }}
      <span class="hljs-attr">gap</span>=<span class="hljs-string">{10}</span>
      <span class="hljs-attr">justify</span>=<span class="hljs-string">"center"</span>
      <span class="hljs-attr">align</span>=<span class="hljs-string">"center"</span>
      <span class="hljs-attr">m</span>=<span class="hljs-string">"auto"</span>
    &gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">w</span>=<span class="hljs-string">"100%"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Image</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"Images/Contact_Bg.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Contact Background"</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">w</span>=<span class="hljs-string">"80%"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>
          <span class="hljs-attr">as</span>=<span class="hljs-string">"h1"</span>
          <span class="hljs-attr">fontSize</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">base:</span> '<span class="hljs-attr">2xl</span>', <span class="hljs-attr">md:</span> '<span class="hljs-attr">3xl</span>', <span class="hljs-attr">sm:</span> '<span class="hljs-attr">3xl</span>' }}
          <span class="hljs-attr">fontWeight</span>=<span class="hljs-string">"bold"</span>
          <span class="hljs-attr">mb</span>=<span class="hljs-string">{3}</span>
        &gt;</span>
          Get In Touch
        <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">Text</span>
          <span class="hljs-attr">as</span>=<span class="hljs-string">"p"</span>
          <span class="hljs-attr">w</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">base:</span> '<span class="hljs-attr">100</span>%', <span class="hljs-attr">md:</span> '<span class="hljs-attr">80</span>%' }}
          <span class="hljs-attr">mt</span>=<span class="hljs-string">{5}</span>
          <span class="hljs-attr">fontSize</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">base:</span> '<span class="hljs-attr">sm</span>', <span class="hljs-attr">md:</span> '<span class="hljs-attr">md</span>', <span class="hljs-attr">lg:</span> '<span class="hljs-attr">lg</span>' }}
          <span class="hljs-attr">mb</span>=<span class="hljs-string">{6}</span>
        &gt;</span>
          Please use the form below to get in touch with us, and our team will
          get back to you as soon as possible. If you prefer to contact us by
          phone, you can find our contact details below.
        <span class="hljs-tag">&lt;/<span class="hljs-name">Text</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Box</span> <span class="hljs-attr">w</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">base:</span> '<span class="hljs-attr">100</span>%', <span class="hljs-attr">md:</span> '<span class="hljs-attr">90</span>%' }}&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
            <span class="hljs-attr">required</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{name}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Name"</span>
            <span class="hljs-attr">mb</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Name"</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
            <span class="hljs-attr">required</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{email}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Input your Email"</span>
            <span class="hljs-attr">mb</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Email"</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Input</span>
            <span class="hljs-attr">required</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{subject}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Subject"</span>
            <span class="hljs-attr">mb</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Subject"</span>
          /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Textarea</span>
            <span class="hljs-attr">value</span>=<span class="hljs-string">{message}</span>
            <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Message"</span>
            <span class="hljs-attr">mb</span>=<span class="hljs-string">{4}</span>
            <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Message"</span>
            <span class="hljs-attr">resize</span>=<span class="hljs-string">"none"</span>
          /&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>
          <span class="hljs-attr">mb</span>=<span class="hljs-string">{4}</span>
          <span class="hljs-attr">isLoading</span>=<span class="hljs-string">{isLoading}</span>
          <span class="hljs-attr">isDisabled</span>=<span class="hljs-string">{isLoading}</span>
          <span class="hljs-attr">onClick</span>=<span class="hljs-string">{handleSubmit}</span>
          <span class="hljs-attr">colorScheme</span>=<span class="hljs-string">"teal"</span>
        &gt;</span>
          Send
        <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">Box</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">Flex</span>&gt;</span></span>
  );
}
</code></pre>
<p>In the code above, we’re importing the various UI components from the Charkra UI library which we’ll use for building the form input.</p>
<p>Now that we’ve created the form inputs, let’s focus on the logical aspect: making the form input functional. Here’s how you can do this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">'react'</span>;
</code></pre>
<p>You import the <code>useState</code> hook (which is a React hook) which lets you effectively declare/add states and manage states in a functional component.</p>
<p>The <code>useState</code> hook declaring states and managing states might sound a bit off to you – but I have an article that’ll help you understand how the <code>useState</code> hook functions: <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-the-usestate-and-useeffect-hooks-in-your-project">Here you go</a>.</p>
<p>Next, you’ll need to declare your state variables. Here’s how you can do that:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> [name, setName] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [email, setEmail] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [subject, setSubject] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [message, setMessage] = useState(<span class="hljs-string">''</span>);
<span class="hljs-keyword">const</span> [isLoading, setIsLoading] = useState(<span class="hljs-literal">false</span>);
<span class="hljs-keyword">const</span> [error, setError] = useState(<span class="hljs-string">''</span>);
</code></pre>
<p>In the code above, the state variable includes the likes of <code>name</code>, <code>email</code>, <code>subject</code>, <code>message</code>, and so on which we’re using to store user inputs from the contact form. Then we’re using <code>setName</code>, <code>setEmail</code>, <code>setSubject</code>, <code>setMessage</code> and so on to manage and update the state in case the initial value changes at some point later.</p>
<p>Next, create a function to handle the form submission:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> handleSubmit = <span class="hljs-keyword">async</span> (e) =&gt; {
  e.preventDefault();
  setIsLoading(<span class="hljs-literal">true</span>);
  setError(<span class="hljs-string">''</span>);
</code></pre>
<p>Here, <code>e.preventDefault()</code> helps prevent the page from reloading when the form is submitted. <code>SetIsLoading(true)</code> shows that the form submission is in progress. And <code>setError(‘ ‘)</code> clears any previous error messages that might have occurred during submission.</p>
<p>Next, create a form validation function to validate the input forms and seek out any errors before the form is finally submitted.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (!name || !email || !subject || !message) {
  setError(<span class="hljs-string">'All fields are required.'</span>);
  setIsLoading(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">return</span>;
}

<span class="hljs-keyword">if</span> (!<span class="hljs-regexp">/\S+@\S+\.\S+/</span>.test(email)) {
  setError(<span class="hljs-string">'Invalid email format.'</span>);
  setIsLoading(<span class="hljs-literal">false</span>);
  <span class="hljs-keyword">return</span>;
}
</code></pre>
<p>Before the form is finally submitted, the code above first checks if all the input fields are filled out. If any field is found empty, it displays an error and immediately the form submission is stopped. The same goes for the email. Emails are arranged and typed out in a specific syntax, and if the email field doesn’t follow that syntax, an error is displayed as well.</p>
<p>Next, create an object which stores the information given by the user when they fill out the form. This information will be sent to the backend.</p>
<pre><code class="lang-javascript">Const formData = {name, email, subject, message };
</code></pre>
<p>Now, create a function that sends your data to the backend:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">try</span> {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">" YOUR API LINK GOES HERE"</span>, {
    <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
    <span class="hljs-attr">headers</span>: { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> },
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify(formData),
  });

  <span class="hljs-keyword">const</span> result = <span class="hljs-keyword">await</span> response.json();
</code></pre>
<p>The <code>fetch</code> response sends the data to the backend API. It uses the <code>post</code> method. When the data is sent to the backend, it’s sent out as a <code>JSON</code> file. Then the data inside the <code>JSON</code> file are all converted into a string.</p>
<p>This is what it looks like when sent:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477266973/7c1a1da7-c7f7-40bc-89f2-a26cb1f444e4.png" alt="7c1a1da7-c7f7-40bc-89f2-a26cb1f444e4" class="image--center mx-auto" width="389" height="149" loading="lazy"></p>
<p>At this point, let’s work on the response handling from the API as well as error handling:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">if</span> (response.ok) {
      alert(result.message || <span class="hljs-string">'Email sent successfully!'</span>);
      setName(<span class="hljs-string">''</span>);
      setEmail(<span class="hljs-string">''</span>);
      setSubject(<span class="hljs-string">''</span>);
      setMessage(<span class="hljs-string">''</span>);
    } <span class="hljs-keyword">else</span> {
      setError(result.error || <span class="hljs-string">'Failed to send email.'</span>);
    }
  } <span class="hljs-keyword">catch</span> (error) {
    setError(<span class="hljs-string">'An unexpected error occurred. Please try again later.'</span>);
  } <span class="hljs-keyword">finally</span> {
    setIsLoading(<span class="hljs-literal">false</span>);
  }
</code></pre>
<p>In the code above, after the user types in their information correctly and submits it, if the message is sent successfully, an alert will be displayed with the message <code>Email sent Successfully</code>. But if the message wasn’t successful – maybe due to how the user typed in their information or due to a failed request – an alert will be displayed as well an error message <code>Failed to send email.</code>.</p>
<p>For handling server errors that might occur due to network issues or due to the API being down, an error message will be displayed <code>An unexpected error occurred. Please try again later.</code>.</p>
<p>At this point, we have successfully built out the frontend aspect of the form. So now we can fully dive into the backend. Let’s get on with it.</p>
<h2 id="heading-backend-setup">Backend Setup</h2>
<p>For the backend, we’ll use <code>Node.js</code>, <code>Dotenv</code>, <code>CORS</code>, <code>Nodemailer</code>, and <code>oAuth2</code>.</p>
<h3 id="heading-backend-libraries-setup">Backend Libraries Setup</h3>
<p>Let’s start by setting up your Node.js server. To do this, you’ll want to create a file inside your backend folder with the name <code>send-email.js</code>. Then in your backend folder, you’ll create a package.json file and install all the dependencies you’ll need.</p>
<p>Start by running <code>npm init -y</code> in your terminal. This creates the Package.json file which manages your project and stores all the dependencies.</p>
<p>Next, let’s go ahead and install the libraries you’ll be using:</p>
<ul>
<li><p><code>Nodemailer</code> enables email sending, as you now know.</p>
</li>
<li><p><code>dotenv</code> loads an environment where you’ll store your <code>.env</code> file.</p>
</li>
<li><p><code>cors</code> allows requests between the frontend and the backend.</p>
</li>
<li><p><code>googleapis</code> provides OAuth2 authentication support for sending emails securely.</p>
</li>
</ul>
<p>You can install these one by one by running the commands <code>npm install nodemailer</code>, <code>npm install dotenv</code>, <code>npm install cors</code>, and <code>npm install googleapis</code>. Or you can install them all at once with:</p>
<pre><code class="lang-bash">npm install nodemailer dotenv cors googleapis
</code></pre>
<p>Note that <code>cors</code> plays an important role in ensuring effective communication between your frontend server and the backend. <a target="_blank" href="https://www.freecodecamp.org/news/access-control-allow-origin-header-explained">You can learn more about CORS here</a>.</p>
<h3 id="heading-oauth2-configuration-setup">OAuth2 Configuration Setup</h3>
<p>Now before you finish setting up the send email function, you first need to configure <code>OAuth2</code> to get access to the tokens and keys you’re using, such as <code>CLIENT_ID</code>, <code>CLIENT_SECRET</code>, <code>REFRESH_TOKEN</code>, and so on.</p>
<p>To set up OAuth2, <a target="_blank" href="https://console.cloud.google.com/projectselector2/home">go here</a> to visit your Google Cloud dashboard. Once it opens, it should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477897924/e6879a15-6835-42e8-a869-8e49b725101a.png" alt="Google Cloud Dashboard" class="image--center mx-auto" width="1914" height="572" loading="lazy"></p>
<p>On the screen, click on “create project” and it’ll take you to a place where you can create your project. It should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742477974830/bd51345f-0af8-4ad0-a912-0a59db8e3fee.png" alt="Google Cloud Project Creation" class="image--center mx-auto" width="1067" height="703" loading="lazy"></p>
<p>After you create your project, it’ll take you to your dashboard with your project name displayed at the top right left corner of the screen. This shows that you have successfully created your project. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478101790/7fa5e621-69c2-4144-ae9c-a3bd9b59a038.png" alt="Google Cloud Dashboard after Project has been created" class="image--center mx-auto" width="1258" height="927" loading="lazy"></p>
<p>After creating the account, click the toggle button at the top left-hand corner of your screen. When it opens, click on the APIs &amp; Services button. A dropdown should then be displayed. Then click on the OAuth consent screen. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478459190/1af14c8f-7cff-4efa-804c-88ba19f0c47c.png" alt="Google Cloud API and Services Process" class="image--center mx-auto" width="861" height="655" loading="lazy"></p>
<p>After that, it should direct you to a new page where you can then configure your project.</p>
<p>The configuration process has four steps, which we’ll go through now.</p>
<h4 id="heading-step-1-add-app-information">Step 1: Add app information</h4>
<p>First, you’ll need to add your app’s information, which includes your app name and user support email. For the app name, go ahead and add your project name there. For the support email, add your email address and click on the ‘Next’ button. It should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478695772/587bef4a-e1e1-4ae8-94e0-f620f4b81c79.png" alt="Project configuration step 1" class="image--center mx-auto" width="767" height="388" loading="lazy"></p>
<h4 id="heading-step-2-set-up-the-audience-section">Step 2: Set up the audience section</h4>
<p>Next, you’ll need to set up the Audience section. In this section, choose the ‘External’ options, which means that others (not only those within the organization) can send messages with the web application. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478724025/59dde0dd-e1f7-445c-9155-64926f71d746.png" alt="Project configuration step 2" class="image--center mx-auto" width="720" height="468" loading="lazy"></p>
<h4 id="heading-step-3-add-contact-information">Step 3: Add contact information</h4>
<p>Now you’ll come to the contact information section, where you’ll need to add your email address.</p>
<h4 id="heading-step-4-agree-to-google-api-services">Step 4: Agree to Google API Services</h4>
<p>Finally, you’ll need to agree to the Google API Services. After that, you can finish the configuration of your project by clicking on the ‘create’ button.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478750231/742f0104-0631-4442-8a69-1266b433a1d1.png" alt="Project configuration step 3" class="image--center mx-auto" width="685" height="264" loading="lazy"></p>
<p>After you’ve completely configured your project, it’ll take you to a page where you can create your client ID. To create it, click on the ‘Create Oauth Client’ button on the screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742478869578/b12e0437-ef27-4127-80fb-d8e36a2714c1.png" alt="Create OAuth Client Section" class="image--center mx-auto" width="1592" height="461" loading="lazy"></p>
<p>This takes you to a place where you’ll add the information about your project. For the “project type/Application type”, choose Web application, and then scroll down and click on the Create button.</p>
<p>After that, your <code>Client ID</code> and <code>Client Secret</code> token should finally be generated. Here is what it looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479023599/004465be-cce9-4b20-aa32-5a4f676f4d03.png" alt="Client ID and Client Secret generation Successful" class="image--center mx-auto" width="642" height="712" loading="lazy"></p>
<p>Next, head to the <a target="_blank" href="https://developers.google.com/oauthplayground/">OAuth Playground</a> where you’ll complete the final setup. Once there, click on the gear button at the top right of the screen. There, just add your <code>client ID</code> and <code>Client Secret</code> which you generated before.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479184829/7885b38b-de54-46fb-9c0d-a0739110dd98.png" alt="Refresh token generation process step 1 " class="image--center mx-auto" width="582" height="770" loading="lazy"></p>
<p>Then on the left, scroll down to ‘Gmail API v1’, click on it, and select the first dropdown option which was ‘<a target="_blank" href="https://mail.google.com/’">https://mail.google.com/’</a>. Then click on ‘Authorize APIs’.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479467364/2f04e0ac-3514-4bc4-b16f-cf163770a5c5.png" alt="Refresh token generation process step 2" class="image--center mx-auto" width="762" height="821" loading="lazy"></p>
<p>This’ll take you to a sign-in with Google page, where you can choose your email account and continue.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479538105/c3470cfa-5867-40a2-a2bc-122334efa752.png" alt="Refresh token generation process step 3" class="image--center mx-auto" width="1381" height="742" loading="lazy"></p>
<p>Then you’ll be redirected back to the OAuth Playground dashboard. At this point, your Authorization code has been generated for you, but what you really need is the <code>Refresh token</code>. So to get it, click on <code>Exchange authorization code for tokens</code>. After that your <code>refresh token</code> should be generated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742479669946/76b6b4a3-1929-4354-abb2-a7f514e04c20.png" alt="Refresh token generation process Completion stage" class="image--center mx-auto" width="619" height="695" loading="lazy"></p>
<p>At this point, your OAuth2 configuration is done! Now what’s left is to store all the tokens you generated in an <code>.env</code> file you’ve created. You’ll also need to set up your send email function using <code>NodeMailer</code>.</p>
<h3 id="heading-nodemailer-setup"><code>Nodemailer</code> Setup</h3>
<p>Now, that you’ve gotten all the tokens you need to create your mailer function, all that remains is to start putting your backend code together.</p>
<p>First, start by loading your <code>.env</code> file into <code>process.env</code> so you can easily access all the tokens you generated. Also, import the libraries you initially installed.</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">require</span>(<span class="hljs-string">"dotenv"</span>).config();
<span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">"nodemailer"</span>);
<span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">"cors"</span>);
<span class="hljs-keyword">const</span> { google } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"googleapis"</span>);
</code></pre>
<p>Next on the line, you’ll need to set up OAuth2. Here, the <code>client ID</code>, and <code>client Secret</code> which you initially generated will be used to authenticate the application and securely request and create access tokens. These will be used for seamlessly sending emails through Google APIs.</p>
<p>You’ll also need to configure the refresh token which lets the application obtain new access tokens automatically without requiring user interaction.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> oAuth2Client = <span class="hljs-keyword">new</span> google.auth.OAuth2(
  process.env.CLIENT_ID,
  process.env.CLIENT_SECRET,
  process.env.REDIRECT_URI
);

<span class="hljs-comment">//setting up refresh token.</span>
oAuth2Client.setCredentials({
  <span class="hljs-attr">refresh_token</span>: process.env.OAUTH_REFRESH_TOKEN,
});
</code></pre>
<p>Since we want the frontend to interact properly with the backend, you’ll want to configure a <code>CORS Middleware</code>. This allows requests from any origin (`*`) as well as allowing POST requests from that origin. Here is how you can do that:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> corsMiddleware = cors({ <span class="hljs-attr">origin</span>: <span class="hljs-string">"*"</span>, <span class="hljs-attr">methods</span>: [<span class="hljs-string">"POST"</span>] });
</code></pre>
<p>Next, create a function to handle <code>CORS</code> and the Request Method. This function applies the <code>CORS</code> middleware to the request in such a way that if the request method is <code>OPTIONS</code>, it responds with a <code>200 status (“preflight OK”)</code>. This means that your request has been approved/allowed by the server because it met the server’s set rules. If the request method is not <code>POST</code>, a response of <code>405 status (“Method not allowed”)</code> will be displayed, showing that your request does not meet the server’s set rule.</p>
<p>Here’s how it’s done:</p>
<pre><code class="lang-javascript">corsMiddleware(req, res, <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">if</span> (req.method === <span class="hljs-string">"OPTIONS"</span>) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">200</span>).send(<span class="hljs-string">"Preflight OK"</span>);
  }

  <span class="hljs-keyword">if</span> (req.method !== <span class="hljs-string">"POST"</span>) {
    <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">405</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Method not allowed"</span> });
  }
</code></pre>
<p>Next, create a function that extracts and validates the input request. This request contains the senders <code>name</code>, <code>email</code>, <code>subject</code>, and <code>message</code>. This function ensures that all the input fields must be filled out and the email must also be written properly. If not, it responds with a <code>400 status</code> error.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> { name, email, subject, message } = req.body;

<span class="hljs-comment">// Validate input</span>
<span class="hljs-keyword">if</span> (!name || !email || !subject || !message) {
  <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"All fields are required."</span> });
}

<span class="hljs-keyword">if</span> (!<span class="hljs-regexp">/^[^\s@]+@[^\s@]+\.[^\s@]+$/</span>.test(email)) {
  <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Invalid email address."</span> });
}
</code></pre>
<p>Up next, you’ll create a function that helps retrieve new access tokens. You’ll also create a Nodemailer transporter function. This transporter was configured to use Gmail’s SMTP service with OAuth2 authentication.</p>
<p>This means whenever a user sends an email, the transporter function first verifies if the Gmail’s SMTP service is ready. If it is, the mail will be verified first with OAuth2, and if the authentication check is successful, the mail will be delivered successfully.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">//Function to retrieve new access token</span>
<span class="hljs-keyword">const</span> accessToken = <span class="hljs-keyword">await</span> oAuth2Client.getAccessToken();
<span class="hljs-keyword">if</span> (!accessToken || !accessToken.token) {
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Failed to retrieve access token."</span>);
}
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Access token retrieved successfully."</span>);

<span class="hljs-comment">/// Creating the Nodemailer Transporter function</span>
<span class="hljs-keyword">const</span> transporter = nodemailer.createTransport({
  <span class="hljs-attr">service</span>: <span class="hljs-string">"gmail"</span>,
  <span class="hljs-attr">auth</span>: {
    <span class="hljs-attr">type</span>: <span class="hljs-string">"OAuth2"</span>,
    <span class="hljs-attr">user</span>: process.env.EMAIL_HOST,
    <span class="hljs-attr">clientId</span>: process.env.CLIENT_ID,
    <span class="hljs-attr">clientSecret</span>: process.env.CLIENT_SECRET,
    <span class="hljs-attr">refreshToken</span>: process.env.OAUTH_REFRESH_TOKEN,
    <span class="hljs-attr">accessToken</span>: accessToken.token,
  },
  <span class="hljs-attr">debug</span>: <span class="hljs-literal">true</span>,
  <span class="hljs-attr">logger</span>: <span class="hljs-literal">true</span>,
});

<span class="hljs-comment">///The function verifying if SMTP server is ready</span>
<span class="hljs-keyword">await</span> transporter.verify();
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"SMTP server is ready to send emails."</span>);
</code></pre>
<p>Lastly, you’ll want to structure your mail in the format it should be displayed in the mailbox of the receiver. You’ll also create an error handling function which displays whenever a mail is sent successfully or whenever an error occurs.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> mailOptions = {
        <span class="hljs-attr">from</span>: <span class="hljs-string">`"<span class="hljs-subst">${name}</span>" &lt;<span class="hljs-subst">${email}</span>&gt;`</span>,
        <span class="hljs-attr">to</span>: process.env.EMAIL_RECEIVE,
        <span class="hljs-attr">replyTo</span>: email,
        subject,
        <span class="hljs-attr">html</span>: <span class="hljs-string">`
          &lt;h1&gt;Name: <span class="hljs-subst">${name}</span>&lt;/h1&gt;
          &lt;p&gt;Email: <span class="hljs-subst">${email}</span>&lt;/p&gt;
          &lt;p&gt;Subject: <span class="hljs-subst">${subject}</span>&lt;/p&gt;
          &lt;p&gt;Message: <span class="hljs-subst">${message}</span>&lt;/p&gt;
          &lt;p&gt;&lt;i&gt;Message from Exesenergy Website&lt;/i&gt;&lt;/p&gt;
        `</span>,
      };
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Mail options:"</span>, mailOptions);

      <span class="hljs-comment">// Send email</span>
      <span class="hljs-keyword">await</span> transporter.sendMail(mailOptions);
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Email sent successfully."</span>);

      <span class="hljs-keyword">return</span> res
        .status(<span class="hljs-number">200</span>)
        .json({ <span class="hljs-attr">status</span>: <span class="hljs-string">"success"</span>, <span class="hljs-attr">message</span>: <span class="hljs-string">"Email sent successfully."</span> });
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error details:"</span>, error);
      <span class="hljs-keyword">return</span> res
        .status(<span class="hljs-number">500</span>)
        .json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Internal Server Error"</span>, <span class="hljs-attr">details</span>: error.message });
    }
</code></pre>
<p>At this point, you have successfully set up both your frontend and backend applications. Now you may want to host them. I decided to host both applications using Vercel and link their URLs together.</p>
<p>Here is the source code to access both the <a target="_blank" href="https://github.com/Derekvibe/ExesEnergyFrontend">frontend</a> and the <a target="_blank" href="https://github.com/Derekvibe/ExesEnergyBackend/blob/main/api/send-email.js">backend</a>.</p>
<p>Here is the final result:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742476641876/69f5123a-570f-4e1a-bbed-6278b54fed7a.gif" alt="Video Representation of How the Send mail function works" class="image--center mx-auto" width="1493" height="820" loading="lazy"></p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>Nodemailer is a popular Node.js module that enables its users to send emails efficiently using different methods like SMTP and OAuth2.</p>
<p>If you've made it this far, I hope I've successfully shown you the importance of Nodemailer and how you can use it to send email messages directly from your website.</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
