」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 建立專業的電子郵件服務:Gmail OAuth Express + Webhooks

建立專業的電子郵件服務:Gmail OAuth Express + Webhooks

發佈於2024-11-03
瀏覽:861

电子邮件通知对于现代 Web 应用程序至关重要。在本指南中,我们将使用 Express.js 和 Gmail 的 OAuth2 身份验证构建安全的电子邮件通知服务。我们的服务将接受 webhook 请求并根据传入数据自动发送电子邮件。

我们正在建设什么

我们将创建一个 Express 服务器:

  • 通过 POST 请求接收 webhook 数据
  • 使用 OAuth2 通过 Gmail 进行身份验证
  • 根据 webhook 负载发送自定义电子邮件
  • 优雅地处理错误

先决条件

  • Node.js 安装在您的计算机上
  • 启用 Gmail API 的 Google Cloud Console 项目
  • OAuth2 凭据(客户端 ID、客户端密钥、刷新令牌)
  • Express.js 和 async/await 的基本了解

项目设置

首先,安装所需的软件包:

npm install express body-parser nodemailer googleapis dotenv

使用您的凭据创建 .env 文件:

CLIENT_ID=your_client_id
CLIENT_SECRET=your_client_secret
REDIRECT_URI=your_redirect_uri
REFRESH_TOKEN=your_refresh_token
[email protected]

如果您在设置这些凭据时遇到任何困难,就像我一样,您可以按照以下步骤操作...

第 1 步:创建新的 Google Cloud 项目:

一个。转到 https://console.cloud.google.com/
b.单击页面顶部的项目下拉列表
c.点击“新建项目”
d.输入项目名称,点击“创建”

Build a Professional Email Service: Gmail OAuth Express   Webhooks

第 2 步:启用 Gmail API:
一个。在左侧边栏中,转到“API 和服务”>“库”
b.搜索“Gmail API”
c.点击“Gmail API”,然后点击“启用”

Build a Professional Email Service: Gmail OAuth Express   Webhooks


第 3 步:配置 OAuth 同意屏幕:
一个。转到“API 和服务”>“OAuth 同意屏幕”
b.选择“外部”作为用户类型,然后单击“创建”
c.填写必填字段:
- 应用程序名称:[您的应用程序名称]
- 用户支持电子邮件:[您的电子邮件]
- 开发者联系信息:[您的电子邮件]
d.点击“保存并继续”
e.在“范围”页面上,单击“添加或删除范围”
f.查找并选择“https://mail.google.com/”范围
g。单击“更新”,然后单击“保存并继续”
h.在“测试用户”页面,点击“添加用户”
我。添加您的 Gmail 地址并点击“保存并继续”
j。查看摘要并单击“返回仪表板”


第 4 步:创建 OAuth2 凭据:
一个。转到“API 和服务”>“凭据”
b.单击“创建凭据”>“OAuth 客户端 ID”
c.选择“Web应用程序”作为应用程序类型
d.名称:[您的应用名称]
e.授权的 JavaScript 来源:添加服务器的域(例如,用于本地开发的 http://localhost:3000)
Build a Professional Email Service: Gmail OAuth Express   Webhooks
f.授权重定向 URI:
- 添加:https://developers.google.com/oauthplayground
- 添加服务器的回调 URL(如果有的话)(例如,http://localhost:3000/auth/google/callback)
g。点击“创建”
h.弹出窗口将显示您的客户端 ID 和客户端密钥。安全地保存这些。


第五步:获取新的刷新令牌:
一个。转到 https://developers.google.com/oauthplayground/

Build a Professional Email Service: Gmail OAuth Express   Webhooks

b.单击右上角的齿轮图标(如设置)
c.单击复选框“使用您自己的 OAuth 凭据”
d.输入您的新客户端 ID 和客户端密钥
e.关闭设置
f.在左侧边栏中,找到“Gmail API v1”
g。选择 https://mail.google.com/
h.点击“授权API”
我。选择您的 Google 帐户并授予请求的权限
j。在下一个屏幕上,单击“将授权码兑换为令牌”
k.从响应中复制“刷新令牌”

如果您在此过程中或测试电子邮件功能时遇到任何问题,请提供您在评论中看到的具体错误消息或行为。


代码解释

我们来一步步分解实现:

1. 初始设置和依赖关系

const express = require("express");
const bodyParser = require("body-parser");
const nodemailer = require("nodemailer");
const { google } = require("googleapis");
require("dotenv").config();

const app = express();
app.use(bodyParser.json());

这部分设置我们的 Express 服务器并导入必要的依赖项。我们使用 body-parser 来解析 JSON 请求,并使用 dotenv 来管理环境变量。

2.OAuth2配置

const oAuth2Client = new google.auth.OAuth2(
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });

我们使用 Google 的身份验证库创建 OAuth2 客户端。这可以使用 Gmail 的 API 处理令牌刷新和身份验证。

3. 邮件发送功能

async function sendEmail(webhookData) {
  const {
    receiver_email, //change data based on your needs
  } = webhookData;

  try {
    const accessToken = await oAuth2Client.getAccessToken();
    const transport = nodemailer.createTransport({
      service: "gmail",
      auth: {
        type: "OAuth2",
        user: process.env.EMAIL_USER,
        clientId: CLIENT_ID,
        clientSecret: CLIENT_SECRET,
        refreshToken: REFRESH_TOKEN,
        accessToken: accessToken,
      },
    });

    const mailOptions = {
      from: `Your Name `,
      to: receiver_email,
      subject: ``, //Add Subject of Email
      html: ``, // Add your HTML template here
    };

    return await transport.sendMail(mailOptions);
  } catch (error) {
    console.error("Error in sendMail function:", error);
    throw error;
  }
}

该函数:

  • 从webhook负载中提取数据,您可以根据需要修改负载
  • 获取新的访问令牌
  • 使用 OAuth2 身份验证创建传输
  • 发送包含自定义内容的电子邮件

4.Webhook端点

app.post("/webhook", async (req, res) => {
  try {
    const webhookData = req.body;
    await sendEmail(webhookData);
    res.status(200).send("Email sent successfully");
  } catch (error) {
    console.error("Error processing webhook:", error);
    res.status(500).send("Error processing webhook");
  }
});

我们的 webhook 端点:

  • 接收POST请求
  • 处理 webhook 数据
  • 发送电子邮件
  • 返回适当的响应

测试

使用curl或Postman测试您的webhook:

curl -X POST http://localhost:4000/webhook \
-H "Content-Type: application/json" \
-d '{
  "receiver_email": "[email protected]",
}'

故障排除

常见问题及解决方案:

  1. 身份验证错误:检查您的 OAuth2 凭据
  2. 令牌过期:确保刷新令牌有效
  3. 缺少数据:验证 webhook 有效负载

结论

您现在拥有一个安全的、OAuth2验证的电子邮件通知系统!此实现为构建更复杂的通知系统提供了坚实的基础,同时保持安全性和可靠性。

希望这篇文章对您设置电子邮件服务有用。

编码愉快! ?

版本聲明 本文轉載於:https://dev.to/yashrajxdev/build-a-professional-email-service-gmail-oauth2-express-webhooks-2gp8?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 為什麼HTML無法打印頁碼及解決方案
    為什麼HTML無法打印頁碼及解決方案
    無法在html頁面上打印頁碼? @page規則在@Media內部和外部都無濟於事。 HTML:Customization:@page { margin: 10%; @top-center { font-family: sans-serif; font-weight: ...
    程式設計 發佈於2025-07-03
  • 如何從PHP中的數組中提取隨機元素?
    如何從PHP中的數組中提取隨機元素?
    從陣列中的隨機選擇,可以輕鬆從數組中獲取隨機項目。考慮以下數組:; 從此數組中檢索一個隨機項目,利用array_rand( array_rand()函數從數組返回一個隨機鍵。通過將$項目數組索引使用此鍵,我們可以從數組中訪問一個隨機元素。這種方法為選擇隨機項目提供了一種直接且可靠的方法。
    程式設計 發佈於2025-07-03
  • Java是否允許多種返回類型:仔細研究通用方法?
    Java是否允許多種返回類型:仔細研究通用方法?
    在Java中的多個返回類型:一種誤解類型:在Java編程中揭示,在Java編程中,Peculiar方法簽名可能會出現,可能會出現,使開發人員陷入困境,使開發人員陷入困境。 getResult(string s); ,其中foo是自定義類。該方法聲明似乎擁有兩種返回類型:列表和E。但這確實是如此嗎...
    程式設計 發佈於2025-07-03
  • 如何在JavaScript對像中動態設置鍵?
    如何在JavaScript對像中動態設置鍵?
    在嘗試為JavaScript對象創建動態鍵時,如何使用此Syntax jsObj['key' i] = 'example' 1;不工作。正確的方法採用方括號: jsobj ['key''i] ='example'1; 在JavaScript中,數組是一...
    程式設計 發佈於2025-07-03
  • 在UTF8 MySQL表中正確將Latin1字符轉換為UTF8的方法
    在UTF8 MySQL表中正確將Latin1字符轉換為UTF8的方法
    在UTF8表中將latin1字符轉換為utf8 ,您遇到了一個問題,其中含義的字符(例如,“jáuòiñe”)在utf8 table tabled tablesset中被extect(例如,“致電。為了解決此問題,您正在嘗試使用“ mb_convert_encoding”和“ iconv”轉換受...
    程式設計 發佈於2025-07-03
  • Python環境變量的訪問與管理方法
    Python環境變量的訪問與管理方法
    Accessing Environment Variables in PythonTo access environment variables in Python, utilize the os.environ object, which represents a mapping of envir...
    程式設計 發佈於2025-07-03
  • 您如何在Laravel Blade模板中定義變量?
    您如何在Laravel Blade模板中定義變量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配變量對於存儲以後使用的數據至關重要。在使用“ {{}}”分配變量的同時,它可能並不總是最優雅的解決方案。 幸運的是,Blade通過@php Directive提供了更優雅的方法: $ old_section =...
    程式設計 發佈於2025-07-03
  • 解決Spring Security 4.1及以上版本CORS問題指南
    解決Spring Security 4.1及以上版本CORS問題指南
    彈簧安全性cors filter:故障排除常見問題 在將Spring Security集成到現有項目中時,您可能會遇到與CORS相關的錯誤,如果像“訪問Control-allo-allow-Origin”之類的標頭,則無法設置在響應中。為了解決此問題,您可以實現自定義過濾器,例如代碼段中的MyFi...
    程式設計 發佈於2025-07-03
  • Java中Lambda表達式為何需要“final”或“有效final”變量?
    Java中Lambda表達式為何需要“final”或“有效final”變量?
    Lambda Expressions Require "Final" or "Effectively Final" VariablesThe error message "Variable used in lambda expression shou...
    程式設計 發佈於2025-07-03
  • 如何在無序集合中為元組實現通用哈希功能?
    如何在無序集合中為元組實現通用哈希功能?
    在未訂購的集合中的元素要糾正此問題,一種方法是手動為特定元組類型定義哈希函數,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    程式設計 發佈於2025-07-03
  • 在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    在Ubuntu/linux上安裝mysql-python時,如何修復\“ mysql_config \”錯誤?
    mysql-python安裝錯誤:“ mysql_config找不到”“ 由於缺少MySQL開發庫而出現此錯誤。解決此問題,建議在Ubuntu上使用該分發的存儲庫。使用以下命令安裝Python-MysqldB: sudo apt-get安裝python-mysqldb sudo pip in...
    程式設計 發佈於2025-07-03
  • Spark DataFrame添加常量列的妙招
    Spark DataFrame添加常量列的妙招
    在Spark Dataframe ,將常數列添加到Spark DataFrame,該列具有適用於所有行的任意值的Spark DataFrame,可以通過多種方式實現。使用文字值(SPARK 1.3)在嘗試提供直接值時,用於此問題時,旨在為此目的的column方法可能會導致錯誤。 df.withCo...
    程式設計 發佈於2025-07-03
  • 在Python中如何創建動態變量?
    在Python中如何創建動態變量?
    在Python 中,動態創建變量的功能可以是一種強大的工具,尤其是在使用複雜的數據結構或算法時,Dynamic Variable Creation的動態變量創建。 Python提供了幾種創造性的方法來實現這一目標。 利用dictionaries 一種有效的方法是利用字典。字典允許您動態創建密鑰並...
    程式設計 發佈於2025-07-03
  • 同實例無需轉儲複製MySQL數據庫方法
    同實例無需轉儲複製MySQL數據庫方法
    在同一實例上複製一個MySQL數據庫而無需轉儲在同一mySQL實例上複製數據庫,而無需創建InterMediate sqql script。以下方法為傳統的轉儲和IMPORT過程提供了更簡單的替代方法。 直接管道數據 MySQL手動概述了一種允許將mysqldump直接輸出到MySQL cli...
    程式設計 發佈於2025-07-03
  • 如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在Java中正確顯示“ DD/MM/YYYY HH:MM:SS.SS”格式的當前日期和時間?
    如何在“ dd/mm/yyyy hh:mm:mm:ss.ss”格式“ gormat 解決方案: args)拋出異常{ 日曆cal = calendar.getInstance(); SimpleDateFormat SDF =新的SimpleDateFormat(“...
    程式設計 發佈於2025-07-03

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3