如何正确传递GMail应用专用密码实现SMTP邮件发送
你的报错和密码传递方式没关系,先把两个基础配置错误改了:
- 你之前调整的
Port := 995、utUseImplicitTLS是POP3收邮件的配置,根本不是SMTP发信的参数。995端口跑的是POP3协议,连接成功后返回的+OK是POP3的标准就绪响应,你拿SMTP客户端去读POP3的响应,当然会报「Reply code is not valid」。 - 你代码里的TLS版本配置不符合Gmail当前的安全要求,现在Gmail已经完全下线TLS1.0、TLS1.1支持,只允许TLS1.2及以上版本连接,你原来只开
sslvTLSv1根本握不上手。
应用专用密码的传递方式
没有任何特殊格式,和你之前传普通账号密码的逻辑完全一致:直接把Google后台生成的16位应用专用密码赋值给smtp.Password属性就行,不需要加特殊前缀、不需要额外编码、不需要传额外参数。
注意要先满足账号侧的前置条件,不然你拿不到有效的应用专用密码:
- 必须先给Google账号开启两步验证,没有开启两步验证的账号不会显示应用专用密码的生成入口
- 生成应用专用密码时选择用途为「邮件」,设备选「其他」自定义个名字就行,生成的16位字符串要立刻保存,关闭页面后无法再次查看。
修正后的可运行代码
你原来的SMTP端口587+显式TLS(utUseExplicitTLS)的配置是对的,把SSL版本改对、确认账号参数填对就行:
email:= TIdMessage.Create (nil); try email.LoadFromFile (FFileName); email.OnInitializeISO:= DoInitializeISO; smtp:= TIdSMTP.Create (nil); try smtp.OnFailedRecipient:= FailedRecipient; ssl:= TIdSSLIOHandlerSocketOpenSSL.Create (smtp); // 修正TLS版本,适配Gmail安全规则 ssl.SSLOptions.SSLVersions:= [sslvTLSv1_2]; smtp.OnStatus := DoStatus; smtp.IOHandler:= ssl; smtp.Host:= 'smtp.gmail.com'; // 用户名要填完整Gmail地址,不要只填@前缀 smtp.Username:= FUsername; // 直接赋值16位应用专用密码,无特殊处理 smtp.Password:= FPassword; smtp.UseTLS:= utUseExplicitTLS; smtp.Port:= 587; smtp.ConnectTimeout := 10000; smtp.Connect; try smtp.Send (email); finally smtp.Disconnect; end; finally ssl.Free; smtp.Free; end; finally email.Free; end;
额外注意事项
- 如果你想用隐式TLS连接SMTP,对应端口是465,
UseTLS参数设为utUseImplicitTLS,绝对不要用995端口发邮件,那是收信端口。 - 本地依赖的OpenSSL DLL版本不能低于1.1.1,太老的版本不支持TLS1.2的现代加密套件,也会连接失败。
- 如果刚改完密码/刚生成应用专用密码出现鉴权失败,等1-2分钟再试,Google的权限同步有短暂延迟。
内容的提问来源于stack exchange,提问作者No'am Newman
相关产品推荐
相关产品推荐

