”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 构建专业的电子邮件服务:Gmail OAuth Express + Webhooks

构建专业的电子邮件服务:Gmail OAuth Express + Webhooks

发布于2024-11-03
浏览:293

电子邮件通知对于现代 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]删除
最新教程 更多>
  • 表单刷新后如何防止重复提交?
    表单刷新后如何防止重复提交?
    在Web开发中预防重复提交 在表格提交后刷新页面时,遇到重复提交的问题是常见的。要解决这个问题,请考虑以下方法: 想象一下具有这样的代码段,看起来像这样的代码段:)){ //数据库操作... 回声“操作完成”; 死(); } ?> ...
    编程 发布于2025-04-21
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-04-21
  • 在Python中如何创建动态变量?
    在Python中如何创建动态变量?
    在Python 中,动态创建变量的功能可以是一种强大的工具,尤其是在使用复杂的数据结构或算法时,Dynamic Variable Creation的动态变量创建。 Python提供了几种创造性的方法来实现这一目标。利用dictionaries 一种有效的方法是利用字典。字典允许您动态创建密钥并分...
    编程 发布于2025-04-21
  • Python高效去除文本中HTML标签方法
    Python高效去除文本中HTML标签方法
    在Python中剥离HTML标签,以获取原始的文本表示Achieving Text-Only Extraction with Python's MLStripperTo streamline the stripping process, the Python standard librar...
    编程 发布于2025-04-21
  • 如何在鼠标单击时编程选择DIV中的所有文本?
    如何在鼠标单击时编程选择DIV中的所有文本?
    在鼠标上选择div文本单击带有文本内容,用户如何使用单个鼠标单击单击div中的整个文本?这允许用户轻松拖放所选的文本或直接复制它。 在单个鼠标上单击的div元素中选择文本,您可以使用以下Javascript函数: function selecttext(canduterid){ if(do...
    编程 发布于2025-04-21
  • 切换到MySQLi后CodeIgniter连接MySQL数据库失败原因
    切换到MySQLi后CodeIgniter连接MySQL数据库失败原因
    无法连接到mySQL数据库:故障排除错误消息要调试问题,建议将以下代码添加到文件的末尾.//config/database.php并查看输出: ... ... 回声'... echo '<pre>'; print_r($db['default']); echo '</pr...
    编程 发布于2025-04-21
  • 如何从PHP中的数组中提取随机元素?
    如何从PHP中的数组中提取随机元素?
    从阵列中的随机选择,可以轻松从数组中获取随机项目。考虑以下数组:; 从此数组中检索一个随机项目,利用array_rand( array_rand()函数从数组返回一个随机键。通过将$项目数组索引使用此键,我们可以从数组中访问一个随机元素。这种方法为选择随机项目提供了一种直接且可靠的方法。
    编程 发布于2025-04-21
  • 在Java中如何为PNG文件添加坐标轴和标签?
    在Java中如何为PNG文件添加坐标轴和标签?
    如何用java 在现有png映像中添加轴和标签的axes和labels如何注释png文件可能具有挑战性。与其尝试可能导致错误和不一致的修改,不如建议在图表创建过程中集成注释。使用JFReechArt import java.awt.color; 导入java.awt.eventqueue; 导入...
    编程 发布于2025-04-21
  • 如何在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 解决方案:的,请访问量很大,并应为procectiquiestate的,并在整个代码上正确格式不多: java.text.simpledateformat; 导入java.util.calendar; 导入java...
    编程 发布于2025-04-21
  • 如何在Java的全屏独家模式下处理用户输入?
    如何在Java的全屏独家模式下处理用户输入?
    Handling User Input in Full Screen Exclusive Mode in JavaIntroductionWhen running a Java application in full screen exclusive mode, the usual event ha...
    编程 发布于2025-04-21
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-04-21
  • Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    Async Void vs. Async Task在ASP.NET中:为什么Async Void方法有时会抛出异常?
    在ASP.NET async void void async void void void void void的设计无需返回asynchroncon而无需返回任务对象。他们在执行过程中增加未偿还操作的计数,并在完成后减少。在某些情况下,这种行为可能是有益的,例如未期望或明确预期操作结果的火灾和...
    编程 发布于2025-04-21
  • 将图片浮动到底部右侧并环绕文字的技巧
    将图片浮动到底部右侧并环绕文字的技巧
    在Web设计中围绕在Web设计中,有时可以将图像浮动到页面右下角,从而使文本围绕它缠绕。这可以在有效地展示图像的同时创建一个吸引人的视觉效果。 css位置在右下角,使用css float and clear properties: img { 浮点:对; ...
    编程 发布于2025-04-21
  • 在Go语言中,`defer`语句后使用`()`的原因及作用
    在Go语言中,`defer`语句后使用`()`的原因及作用
    在go 考虑示例:尝试递延函数f本身,这是没有意义的。相反,正确的语法为: defer f(),此构建一个闭合,在激活defer语句时捕获当前上下文并执行函数f。外括号立即执行闭合,以确保在执行延期语句之后进行函数调用。defer func(n int) { fmt.Println(n) }(i)...
    编程 发布于2025-04-21
  • CSS强类型语言解析
    CSS强类型语言解析
    您可以通过其强度或弱输入的方式对编程语言进行分类的方式之一。在这里,“键入”意味着是否在编译时已知变量。一个例子是一个场景,将整数(1)添加到包含整数(“ 1”)的字符串: result = 1 "1";包含整数的字符串可能是由带有许多运动部件的复杂逻辑套件无意间生成的。它也可以是故意从单个真理...
    编程 发布于2025-04-21

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3