SMTP简单邮件传输协议(C/C++ 发送电子邮件)
SMTP是用于通过Internet发送电子邮件的协议。电子邮件客户端(如Microsoft Outlook或macOS Mail应用程序)使用SMTP连接到邮件服务器并发送电子邮件。邮件服务器还使用SMTP将邮件从一个邮件服务器交换到另一个。它不用于从服务器下载电子邮件;相反,IMAP和POP3协议检索邮件。
SMTP客户端首先通过TCP与邮件服务器建立连接。然后,客户端将消息推送到服务器,服务器会检查收件人的电子邮件地址,看看他们是否与发件人在同一个域上;如果他们是,它可以传递信息。否则,它会运行DNS查询来查找收件人邮件服务器的IP地址。然后,邮件服务器与目标邮件服务器建立另一个SMTP连接以发送邮件。
SMTP的基本命令
正如我们前面提到的,SMTP命令是一组代码,为服务器之间的电子邮件传输提供动力。以下是您应该注意的基本SMTP命令:
HELO或EHLO(你好):这是开始整个电子邮件发送过程的关键命令。电子邮件客户端正在向SMTP服务器标识自己。这是一个对话的开始,通常涉及服务器发回一个HELO命令及其域名/IP地址。
MAIL FROM:根据标识命令,发件人将共享指定邮件发件人的代码。这会列出电子邮件地址,并告诉SMTP服务器新事务即将开始。从这里开始,服务器重置所有内容,并准备接受电子邮件地址。一旦被接受,它将回复一个250 OK的回复代码。
RCPT TO(Recipient TO):下一个命令位于250 OK回复代码之后,该代码用于识别电子邮件的发送对象。同样,SMTP服务器使用相同的代码进行响应,此时可以使用不同收件人的电子邮件地址发送另一个RCPT TO命令。这可以根据需要来回多次,具体取决于收到电子邮件的人数。
DATA 数据:这会触发客户端和服务器之间的数据传输。所有邮件内容都将移动到SMTP服务器,SMTP服务器将以345回复代码进行响应。消息的内容被传输到服务器,在服务器中,一个点被单独发送到一行中,以表示消息的结束。如果接受并准备好交付,服务器将发送另一个250 OK代码。此时,邮件正在发送给收件人的途中。
QUIT:发送电子邮件后,客户端向服务器发送QUIT命令,切断连接。如果已成功关闭,服务器将回复221代码。
RSET(Reset):当邮件事务需要中止时,会将此命令发送到服务器。它不会关闭连接,但会重置所有内容,并删除有关电子邮件和相关方的所有以前的数据。当出现错误时,通常会使用此方法,例如输入错误的收件人信息,并且需要重新启动流程。
将这些命令想象成允许电子邮件服务器之间进行对话的语言。他们的聊天看起来有点像这样:

还有其他SMTP命令可以处理身份验证并增强安全性,例如AUTH和STARTTLS。如果您有兴趣了解它们或查看SMTP在工作中的示例,请阅读本SMTP命令指南。
Linux使用mail配合smtp发送邮件
邮件安装工具:
yum -y install mailx
yum -y install sendmail
开启与关闭邮件服务:
systemctl enable sendmail
systemctl stop sendmail
开启邮箱imap/smtp服务
我这里使用的是163的邮箱,步骤如下:
登录邮箱后,点击页面顶部的“设置”菜单,在下拉框中点击“POP3/SMTP/IMAP”项

由于我这里已经开启过,就不再演示了。初始勾选后会让你填写手机号码,发送验证码,成功填写后,会让你输入授权码,这个是作为smtp登录的密码使用的,详情请看163的smtp说明
配置发送的邮箱和密码,注意不是你的邮箱登录密码。
# vi /etc/mail.rc在底部添加:
set from="xxx@163.com"
set smtp=smtp.163.com
set smtp-auth-user=xxx@163.com
set smtp-auth-password=自己填写的授权码
set smtp-auth=login
测试发送
echo -e “This is a fine test body…” | mail -s “TestMail” xxx@163.com

为帮助您熟悉使用 SMTP 协议发送邮件的流程,提供以下 telnet 命令会话过程示例,来描述 SMTP 命令会话过程。
备注:其中 S 代表服务器,C 代表客户端。可以使用 Linux 命令 echo -n Content|base64 进行 base64 编码。
$telnet smtpdm.aliyun.com 25
S:220 163.com Anti-spam GT for Coremail System (163com[20141201])
C:EHLO test.com
S:250 OK
C:AUTH LOGIN
S:334 dXNlcm5hbWU6
C:YSoqKkBleGFtcGxlLm5ldA== 备注:用户名a***@example.net的base64编码
S:334 UGFzc3dvcmQ6
C:dGVzdA== 备注:用户密码test的base64编码
S:235 Authentication successful
C:MAIL FROM: <a***@example.net> 备注:注意用 <> 将发件人扩起来
S:250 Mail Ok
C:RCPT TO: <a***@example.net>
S:250 Rcpt Ok
C:DATA
S:354 End data with <CR><LF>.<CR><LF>
C:subject: test
C:from: <a***@example.net>
C:to: <a***@example.net>
C:
C:test
C:.
S:Data Ok: queued as freedom ###envid=148316944
C:QUIT
S:221 Bye
了解SMTP错误代码
电子邮件发送过程并不总是像上面我们的电子邮件服务器聊天的例子那样顺利。反弹、阻止或其他问题可能会阻止发送电子邮件。在这种情况下,接收服务器可以使用SMTP错误代码通知您问题,了解它们的含义可以帮助您诊断和修复电子邮件传递障碍。
例如,以下是两组经常出现的SMTP错误:
4.X.X持续瞬态故障:这些错误代码以数字“4”开头,后面跟着另外两个数字。它们通常意味着邮件服务器出现临时故障。再次重复该命令可以消除错误,但服务器经常使用这些代码来阻止不受信任的发件人。
5.X.X永久错误:这些错误代码以数字“5”开头,后面跟着两个数字。它们通常表示SMTP连接已断开。如果你试图重新发送电子邮件,很可能仍然会导致同样的错误。
#define SMTP_SERV_NOSERVICE 421 /* Server error: <domain> Service not available, closing transmission channel */
#define SMTP_SERV_NOMAILBOX 450 /* Server error: Requested mail action not taken: mailbox unavailable */
#define SMTP_SERV_ACTABORT 451 /* Server error: Requested action aborted: local error in processing */
#define SMTP_SERV_NOSTORAGE 452 /* Server error: Requested action not taken: insufficient system storage */
#define SMTP_SERV_NOTLS 454 /* Server error: TLS not available */
#define SMTP_SERV_SYNTAX 500 /* Syntax error, command unrecognised */
#define SMTP_SERV_SYNTAX_P 501 /* Server error: Syntax error in parameters or arguments*/
#define SMTP_SERV_UNKNOWN 502 /* Server error: Unknown command */
#define SMTP_SERV_BADSEQ 503 /* Server error: Bad sequence of commands */
#define SMTP_SERV_NCMDPAR 504 /* Server error: Command parameter not implemented */
#define SMTP_SERV_NOACCMAIL 521 /* Server error: <domain> does not accept mail (see rfc1846) */
#define SMTP_SERV_STARTTLS 530 /* Server error: Start TLS needed */
#define SMTP_SERV_AUTHERR 535 /* Server error: Authentication failed */
#define SMTP_SERV_NOMBOXNM 550 /* Server error: Requested action not taken: mailbox unavailable */
#define SMTP_SERV_USRNOLOCL 551 /* Server error: User not local; please try <forward-path> */
#define SMTP_SERV_EXCSTOR 552 /* Server error: Requested mail action aborted: exceeded storage allocation */
#define SMTP_SERV_MBXNMNALL 553 /* Server error: Requested action not taken: mailbox name not allowed */
#define SMTP_SERV_TMUNKCOM 554 /* Server error: Transaction failed*/
SMTP与其他电子邮件协议有何不同?
回想一下SMTP的定义,你会记得我们说过它是许多电子邮件协议之一。POP和IMAP是另外两种最常用的电子邮件协议。
这些协议之间的主要区别在于,SMTP是将电子邮件从一个未知的邮件服务器发送或“推送”到另一个未知邮件服务器的唯一协议。POP和IMAP是用于从自己的邮件服务器接收或“拉取”收件人邮件的协议。因此,POP和IMAP仅限制将邮件传输到经过验证的邮件服务器。它们不能用于您自己网络之外的通信。
发送过程中的不同协议:SMTP用于发送电子邮件,POP和IMAP用于接收邮件
下面,我们将更深入地解释POP和IMAP的工作原理以及它们与SMTP的区别。
POP
POP代表邮局协议,用于接收传入消息。最新的版本是POP3,上次更新是在1988年。
这个协议之所以得名,是因为它的运作方式就像数字领域中现实生活中的邮局。POP3将接收电子邮件,并为客户保留这些电子邮件,直到他们收到为止。所有电子邮件都下载并存储在本地,这对于只使用一台计算机查看电子邮件的人来说是一个方便的解决方案。它也被企业普遍使用,因此员工可以在离线时查看电子邮件。
POP和SMTP有何不同?
SMTP是一种消息传输协议,而POP是一种邮件访问协议。换句话说,SMTP用于将邮件从一个用户发送到另一个用户,而POP用于接收电子邮件。
SMTP使用两次:一次是在发件人和电子邮件服务器之间建立连接并发送信息时,第二次是在发送信息并连接到收件人时。POP在接收者和他们的邮件服务器之间只使用一次。
IMAP
IMAP代表Internet邮件访问协议。简而言之,IMAP将邮件存储在电子邮件服务器上,但用户可以访问该服务器来检查和配置他们的电子邮件。这与POP的区别在于IMAP使用云服务器,因此任何设备都可以对电子邮件进行身份验证和分类。许多电子邮件用户更喜欢IMAP而不是POP,因为它既方便又高效。
IMAP和SMTP有何不同?
SMTP是一种消息传输协议,而IMAP是一种邮件访问协议(与POP类似)。因此,当SMTP发送邮件并处理传出的电子邮件时,IMAP只检索邮件并处理传入的电子邮件。
SMTP简单邮件传输协议(C/C++ 发送电子邮件)
int smtp_init(SMTP_Client **smtp);int smtp_free(SMTP_Client **smtp);int smtp_connect(SMTP_Client *smtp, const char *smtpHostName, const unsigned short smtpPort, int security);int smtp_close(SMTP_Client *smtp);ssize_t smtp_createLetter(SMTP_Client *smtp,int textFormat,const char *fromName, const char *fromMail,const char *toName, const char *toMail,const char *mailSubject, const char *mailBody);ssize_t smtp_attachFile(SMTP_Client *smtp, const char *filePath);ssize_t smtp_endLetter(SMTP_Client *smtp);int smtp_login(SMTP_Client *smtp, const char *smtpLogin, const char *smtpPasswd);int smtp_sendLetter(SMTP_Client *smtp);static ssize_t smtp_sendData_real(const char *file, int line, SMTP_Client *smtp, const unsigned char *data, size_t size)
{if(smtp->debugPrint){char *duped = strdup((const char*)data);removeEndlEnding(duped);fprintf(smtp->debugStream, "[%s][%d] OUT>>: %s\n", file, line, duped);free(duped);}if(smtp->p->ssl)return smtp_sslSend(smtp, data, size);elsereturn socketWrite(smtp->p->socketFd, data, size);
}static ssize_t smtp_recvData_real(const char *file, int line, SMTP_Client *smtp, unsigned char *data, size_t size)
{ssize_t ret = 0;if(smtp->p->ssl)ret = smtp_sslRecv(smtp, data, size);elseret = socketRead(smtp->p->socketFd, data, size);if(smtp->debugPrint){char *duped = strdup((const char*)data);removeEndlEnding(duped);fprintf(smtp->debugStream, "[%s][%d] IN <<: %s\n", file, line, duped);free(duped);}return ret;
}static int recvStatus(SMTP_Client *smtp, const unsigned char *recvString)
{
...if(smtp->debugPrint)fprintf(smtp->debugStream, "[%s][%d] status = %d\n", __FILE__, __LINE__, atoi(statusStr));switch(reply){case 250: case 235: case 354: case 334: case 221: break;default:if(smtp->debugPrint){fprintf(smtp->debugStream, "Received status is an error!");}return -1;}return 0;
}int main()
{ssize_t ret;SMTP_Client *smtp;int security = SMTP_NONSECURE;const char *smtpServer = SMTP_SAMPLE_HOSTNAME;const char *smtpLogin = SMTP_SAMPLE_LOGIN;const char *smtpPassword = SMTP_SAMPLE_PASSWORD;const char *letterSubj = "Hello :3";const char *letterBody = "this is test!, <b>My Little Vixie!</b>! <span style=\"font-size: 50px;\">:3</size><br>";if(smtp_init(&smtp) < 0){fprintf(stderr, "Can't initialize SMTP!\n");return 1;}/* 要打开调试输出,请设置这些标志 */smtp->debugPrint = 1;smtp->debugStream = stderr;/* 初始化数据 */ret = smtp_createLetter(smtp,SMTP_TextHTML,SMTP_SAMPLE_NAME_FROM, SMTP_SAMPLE_MAIL_FROM,SMTP_SAMPLE_NAME_TO, SMTP_SAMPLE_MAIL_TO,letterSubj, letterBody);#if SMTP_SAMPLE_USE_SSLsecurity = SMTP_SSL;#endifif(smtp_connect(smtp, smtpServer, SMTP_SAMPLE_PORT, security) < 0){fprintf(stderr, "connect FAILED ... [%s]\n", smtp->errorString);smtp_free(&smtp);return 1;}printf("connect OK ...\n");ret = smtp_login(smtp, smtpLogin, smtpPassword);if(ret < 0){fprintf(stderr, "auth FAILED ... [%s]\r\n", smtp->errorString);smtp_free(&smtp);return 1;}printf("auth OK ...\n");ret = smtp_sendLetter(smtp);if(ret < 0){fprintf(stderr, "send FAIL ... [%s]\n", smtp->errorString);smtp_free(&smtp);return 1;}printf("send OK ...\n");smtp_free(&smtp);return 0;
}
运行结果:

If you need the complete source code, please add the WeChat number (c17865354792)
总结
SMTP代表简单邮件传输协议。SMTP是一套交互准则,允许软件通过互联网传输电子邮件,称为简单邮件传输协议。
SMTP的主要目标是用于设置服务器之间的通信规则。服务器有一种识别自己的方式,并宣布他们试图执行什么样的通信。他们还有一种处理错误的方法,例如错误的电子邮件地址。例如,如果收件人地址错误,则会收到带有某种错误消息的服务器回复。
Welcome to follow WeChat official account【程序猿编码】
参考:rfc821.txt
相关文章:
SMTP简单邮件传输协议(C/C++ 发送电子邮件)
SMTP是用于通过Internet发送电子邮件的协议。电子邮件客户端(如Microsoft Outlook或macOS Mail应用程序)使用SMTP连接到邮件服务器并发送电子邮件。邮件服务器还使用SMTP将邮件从一个邮件服务器交换到另一个。它不用于从服务器下载电子邮件;相…...
uploads靶场通关(1-11关)
Pass-01(JS校验) 看题目我们准备好我们的php脚本文件,命名为1.php 上传该php文件,发现上传失败 方法一:将浏览器的JavaScript禁用 然后就能上传了 方法二: 查看源码,发现只能上传以下形式的文…...
6.1黄金探底回升是否到顶,今日多空如何布局
近期有哪些消息面影响黄金走势?今日黄金多空该如何研判? 黄金消息面解析:周三(5月31日)黄金期货价格攀升,美国国债收益率下降推动金价升至一周最高收盘位。美市尾盘,现货黄金收报1962.42美元/盎司,上升3…...
自定义ViewGroup实现流式布局
目录 1、View的绘制流程 2、自定义ViewGroup构造函数的作用 3、onMeasure 方法 3.1、View的度量方式 3.2、onMeasure方法参数的介绍 3.3、自定义ViewGroup onMeasure 方法的实现 4、onLayout方法 5、onDraw方法 6、自定义View的生命周期 7、自定义流式布局的实现 扩展ÿ…...
Git版本控制
目录 版本控制 概念 为什么需要版本控制? 常见的版本控制工具 Git 1、安装 2、了解基本的Linux命令 3、配置git 用户名和邮箱 4、git 工作模式 5、git 项目管理 6、git 分支 托管平台 远程仓库 Gitee 关联多个远程库 Git服务器 Git GUI 版本控制 概…...
若依之权限处理
若依之权限处理 若依前后端不分离版本使用的是shiro进行权限控制,本文主要是对shiro在若依中的使用进行分析。 RBAC权限模型 RBAC是指基于角色的访问控制。其基本思想是,对系统的各种权限不是直接授予具体的用户,而是在用户集合与权限集合…...
华为OD机试真题 Java 实现【矩阵最大值】【2023 B卷 100分】,附详细解题思路
一、题目描述 给定一个仅包含0和1的N*N的二维矩阵,请计算二维矩阵的最大值。 计算规则如下: 1、每行元素按下标顺序组成一个二进制数(下标越大越排在低位),二进制数的值就是该行的值。矩阵各行值之和为矩阵的值。 2、允许通过向左或向右整体循环移动每行元素来改变各元…...
ModuleNotFoundError: No module named ‘transformers_modules.chatglm-6b_v1‘的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
MMPretrain代码课
安装注意事项 训练时需要基于算法库源码进行开发,所以需要git clone mmpretrain仓库。如果只调用,则pip install 即可。 from mmpretrain import get_model, list_models,inference_model分别用于模型的获取、例举、推理 此时还没加载预训练权重 tor…...
Selenium自动化程序被检测为爬虫,怎么屏蔽和绕过
Selenium 操作被屏蔽 使用selenium自动化网页时,有一定的概率会被目标网站识别,一旦被检测到,目标网站会拦截该客户端做出的网页操作。 比如淘宝和大众点评的登录页,当手工打开浏览器,输入用户名和密码时,…...
Nvidia Jetson Orin:开发技巧
Jetson PXXX定义 P2180 -> Jetson TX1 P3310 -> Jetson TX2 P3489 -> Jetson TX2i P3448 -> Jetson Nano devkit P3448-0020 -> Jetson Nano production module P2888 -> Jetson Xavier P2888-0060 -> Jetson Xavier-8GB P3701 -> Jetson AGX Orin D…...
为什么需要 git 和 相关的小知识
为什么需要git和相关的小知识 先看一个实际需求,引出Git 问题: 公司五一活动计划 ● 先说一个最简单的情况,比如你做了公司五一活动计划书(如图) 解决方案: 版本管理工具(Git) 一句话: Git 是目前最流行的分布式版本控制软件 Git 是怎么来的? Git…...
(详解)vue中实现主题切换的三种方式
目录 一、背景 二、实现思路 方法1:定义全局的CSS变量 方法2:切换已定义好的css文件 方法3:切换顶级CSS类名 (需使用css处理器,如sass、less等) 一、背景 在我们开发中我们会遇到像是需要切换程序风格、主题切换啦这种应用场景。 参考大佬…...
英国皇家植物园采用机器学习预测植物抗疟性,将准确率从 0.46 提升至 0.67
内容一览:疟疾是严重危害人类生命健康的重大传染病,研究人员一直在致力于寻找新的植物源性抗疟疾化合物,以研发相关药物。近期英国皇家植物园利用机器学习 算法 有效预测了植物抗疟性,该研究成果目前已发表在《Frontiers in Plant…...
基于Locust实现MQTT协议服务的压测脚本
一、背景简介 业务背景大概介绍一下,就是按照国标规定,车辆需要上传一些指定的数据到ZF的指定平台,同时车辆也会把数据传到企业云端服务上,于是乎就产生了一些性能需求。 目前我们只是先简单的进行了一个性能场景的测试…...
AURIX TC3XX Cached PFLASH与Non-Cached PFLASH的区别
Cached ? Non-Cached? 在阅读TC3XX的用户手册时,在内存映射表中,有两个segment都是Program Flash,而且大小都一样是3M,一个是segment 8 另一个是segment10 这难免让人产生疑惑,二者区别在哪? …...
uniapp开发小程序-显示左滑删除效果
一、效果图: 二、代码实现: <template><view class"container"><view class"myorderList"><uni-swipe-action><uni-swipe-action-item class"swipe-action-item" :right-options"option…...
FPGA 的数字信号处理:Verilog 实现简单的 FIR 滤波器
该项目介绍了如何使用 Verilog 实现具有预生成系数的简单 FIR 滤波器。 绪论 不起眼的 FIR 滤波器是 FPGA 数字信号处理中最基本的模块之一,因此了解如何将具有给定抽头数及其相应系数值的基本模块组合在一起非常重要。因此,在这个关于 FPGA 上 DSP 基础…...
使用粒子群优化算法(PSO)辨识锂电池二阶RC模型参数(附MATLAB代码)
目录 一、原理部分 二、代码详解部分 三、结果及分析 一、原理部分 PSO算法由美国学者于 1995 年提出,因其算法简单、效果良好,而在很多领域得到了广泛应用。该算法的起源是模拟鸟群的觅食过程,形成一种群体智能搜索算法。 其核心是&#…...
如何利用地面控制点实现倾斜摄影三维模型数据的几何坐标变换和纠正?
如何利用地面控制点实现倾斜摄影三维模型数据的几何坐标变换和纠正? 倾斜摄影是一种在空中拍摄地表物体的技术,可以获得高分辨率、高精度的三维模型数据,广泛应用于城市规划、建筑设计、土地管理等领域。然而,由于航拍时无法避免姿…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...
鸿蒙Navigation路由导航-基本使用介绍
1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…...
本地部署drawDB结合内网穿透技术实现数据库远程管控方案
文章目录 前言1. Windows本地部署DrawDB2. 安装Cpolar内网穿透3. 实现公网访问DrawDB4. 固定DrawDB公网地址 前言 在数字化浪潮席卷全球的背景下,数据治理能力正日益成为构建现代企业核心竞争力的关键因素。无论是全球500强企业的数据中枢系统,还是初创…...
Angular中Webpack与ngx-build-plus 浅学
Webpack 在 Angular 中的概念 Webpack 是一个模块打包工具,用于将多个模块和资源打包成一个或多个文件。在 Angular 项目中,Webpack 负责将 TypeScript、HTML、CSS 等文件打包成浏览器可以理解的 JavaScript 文件。Angular CLI 默认使用 Webpack 进行项目…...
