使用 SMTP 协议发送邮件问题求教,我自己是真解决不了 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tiRolin
V2EX    Java

使用 SMTP 协议发送邮件问题求教,我自己是真解决不了

  •  
  •   tiRolin 146 天前 3466 次点击
    这是一个创建于 146 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有要求如下

    websocket 连接/smtp 端点,模拟 SMTP 协议发送邮件,发件地址: [email protected] ,收件地址 [email protected] ,邮件内容 Hello World 。请注意:大小写敏感,websocket 连接仅保留 1 分钟左右,断了需要重连并重头发送 SMTP 命令

    可以确定发送的地址是 wss://interview-test.nullht.com/smtp

    我按照他的要求,写出了下面的代码,其他的不重要,我们直接看我发送请求的格式

     private void initializeCommands() { commandQueue.clear(); commandQueue.add("EHLO mine.com\r\n"); commandQueue.add("MAIL FROM:<[email protected]>\r\n"); commandQueue.add("RCPT TO:<[email protected]>\r\n"); commandQueue.add("DATA\r\n"); // 注意:邮件内容需要包含完整格式 commandQueue.add( "From: [email protected]\r\n" + "To: [email protected]\r\n" + "Subject: Hello\r\n" + "\r\n" + // 空行分隔头部和正文 "Hello World\r\n" + ".\r\n" // 结束符 ); commandQueue.add("QUIT\r\n"); } 

    这个代码可以得到下面的响应:

    Sending command: EHLO mine.com Server response: 220 邮件服务器准备就绪 Server response: 250 很高兴认识你 Sending command: MAIL FROM:<[email protected]> Server response: 250 发件人已接受 Sending command: RCPT TO:<[email protected]> Server response: 250 收件人已接受 Sending command: DATA Server response: 500 命令不被识别 

    显然是 DATA 后的内容有问题,其他的都没毛病。但是我参照下面的教程

    https://blog.csdn.net/weixin_39833509/article/details/88965720

    感觉这个格式也没问题啊,我试了好久了都没搞出来到底哪里有问题,什么 AI 、谷歌全试过了,有没有大佬救一下,小弟我是真不行了,我先谢谢各位了

    26 条回复    2025-05-20 16:27:48 +08:00
    lemonda
        1
    lemonda  
       146 天前
    不懂,但是以前排查过一个收不到信的情况,看看 DATA 的邮件模板是 CRLF 还是 LF
    phrack
        2
    phrack  
       146 天前
    这也太底层了,email 的协议又很古老复杂,现在不都是用第三方发信直接 rest api 就完了,第三方帮你屏蔽了底层细节了。
    poxiaogg
        3
    poxiaogg  
       146 天前
    不需要\r\n 结尾
    ```
    commandQueue.add("DATA");
    ```
    bingfengfeifei
        5
    bingfengfeifei  
       146 天前
    看了下 Suricata 解析 smtp 的代码,看上去没问题啊 说不定是服务器实现有问题
    tiRolin
        6
    tiRolin  
    OP
       146 天前
    @bingfengfeifei 服务器不太可能有问题,因为这个服务器不是我的,而是公司提供的
    ZiLong
        7
    ZiLong  
       146 天前
    捞服务器日志看下,有可能错的是服务器实现呢
    hefish
        8
    hefish  
       146 天前
    \r\n 改成 \n\r 看看。。
    这个协议会话没问题。 我 20 年前搞邮件服务器时候,手动 telnet 25 测试发信也是这么输入的。
    gesse
        9
    gesse  
       146 天前
    是不是先要验证执行“AUTH LOGIN\r\n”命令?
    daxy223
        10
    daxy223  
       146 天前
    yinmin
        11
    yinmin  
       145 天前 via iPhone
    用 gpt 或 claude 写一个 websocket to tcp 的桥接程序,还原出 smtp ,然后用 java 内置的发邮件功能试试。

    自己手搓基于邮件协议的代码,中文编码、html 邮件、附件功能都是有工作量的。
    yinmin
        12
    yinmin  
       145 天前 via iPhone
    你可以问问公司是否能提供 smtp ( 25 端口)或者 smtps ( 465 端口),可以直接用 java 内置的发邮件功能;或者是否提供高级的邮件 api ,输入 from 、to 、subject 、mailbody 能直接发邮件。

    基于 smtp 协议让员工手搓,感觉有点扯了。
    jasn56
        13
    jason56  
       145 天前
    估计是服务端需要验证,试试 AUTH LOGIN / USER /PASS
    gtese
        14
    gtese  
       145 天前
    去问下服务器是不是支持匿名,看看匿名怎么写, 如果是需要验证,再去找下验证怎么写。
    smtp 出故障的时候,用 telnet 一条条命令试。试成了再去用代码。
    hytex
        15
    hytex  
       145 天前
    这个已经玩过了,直接给你发结果
    import asyncio
    import websockets

    async def send_smtp_commands():
    uri = "wss://interview-test.nullht.com/smtp" # 根据实际情况修改为 wss:// 或 ws://

    try:
    async with websockets.connect(uri) as websocket:
    # 等待服务器欢迎语(类似于 220 开头的回应)
    print(await websocket.recv())

    # 按照 SMTP 协议逐步发送命令
    await websocket.send("HELO localhost")
    print(await websocket.recv())

    await websocket.send("MAIL FROM:<[email protected]>")
    print(await websocket.recv())

    await websocket.send("RCPT TO:<[email protected]>")
    print(await websocket.recv())

    await websocket.send("DATA")
    print(await websocket.recv())

    await websocket.send("Hello World")
    # print(await websocket.recv())


    await websocket.send(".")
    print(await websocket.recv())


    await websocket.send("QUIT")
    print(await websocket.recv())

    except Exception as e:
    print(f"连接或发送失败: {e}")

    asyncio.run(send_smtp_commands())
    hytex
        16
    hytex  
       145 天前
    @hytex 自己格式化一下 0.0
    lucasdev
        17
    lucasdev  
       145 天前
    宇宙的终极最终答案:42
    是因为这个服务器“只识别单行命令的,要一行行发送,包括最后的.” 参考 https://linux.do/t/topic/638484/24

    都从哪看到的这个
    jackOff
        18
    jackOff  
       145 天前
    就这么说吧,写邮件的第三方库都没几个在认真维护,我蹲一个 email.message_from_bytes 的内存爆炸问题都等了好几年了今年才有热心网友愿意自己优化设计,https://github.com/python/cpython/issues/115512
    pulutom40
        19
    pulutom40  
       145 天前 via iPhone
    什么鬼? smtp 协议是基于 tcp 的,websocket 是什么鬼? ws 的话就不是原始的 smtp 协议了,这种出问题要问提供给你 ws 协议的服务方。只看 smtp 命令的话没啥问题,你可以使用 telnet 模拟客户端给 gmail 发信测试
    pulutom40
        20
    pulutom40  
       145 天前 via iPhone
    另外,你都不是基于 tcp 在投件,那你应该是需要发件吧?发件一般是需要先登录的
    teaser
        21
    teaser  
       145 天前
    别在代码里测试了,直接 telnet 模拟发送测试吧
    unused
        22
    unused  
       145 天前
    等服务器回复再发下一条
    0x663
        23
    0x663  
       145 天前
    好奇基于 websocket 协议的邮件是什么样的
    dreamage
        24
    dreamage  
       145 天前
    smtp 套 wss 什么骚操作
    tiRolin
        25
    tiRolin  
    OP
       145 天前
    @dreamage 我不太懂,所以我是直接通过 AI 写的,我也不知道该怎么办,他这个问题我之前都没接触过
    julyclyde
        26
    julyclyde  
       145 天前
    smtp 协议没问题
    不过你得先问问这个 smtp 是不是需要先 auth
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     850 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 20:20 PVG 04:20 LAX 13:20 JFK 16:20
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86