You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用C#的TcpClient发送邮件是否可行?(作业要求用Socket实现)

完全没问题!用TcpClient手动实现SMTP发邮件是完全可行的——毕竟SmtpClient底层本身就是基于TCP连接来和SMTP服务器交互的,你只是把它封装好的步骤手动走一遍而已。

你的代码已经迈出了第一步(连接到SMTP服务器),但还缺少关键的SSL握手和SMTP命令交互环节——因为smtp.gmail.com:465是SSL加密端口,直接发命令服务器不会响应,得先通过SslStream完成加密握手,再一步步执行SMTP协议的标准命令。

我给你补全完整的实现代码,附带详细注释,刚好适配你的需求:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

class ManualSmtpSender
{
    static void Main(string[] args)
    {
        // 替换成你自己的邮箱配置(Gmail需要应用专用密码,下面会说明)
        string smtpServer = "smtp.gmail.com";
        int smtpPort = 465;
        string senderEmail = "your-account@gmail.com";
        string senderPassword = "your-app-specific-password"; // 重点:Gmail需要这个,不是普通密码
        string recipientEmail = "target@example.com";
        string emailSubject = "Test Email via TcpClient";
        string emailBody = "Hey there! This email was sent using raw TCP and SMTP commands for my homework.";

        using (TcpClient tcpClient = new TcpClient())
        {
            try
            {
                // 1. 连接到SMTP服务器
                tcpClient.Connect(smtpServer, smtpPort);
                Console.WriteLine("Connected to SMTP server successfully.");

                // 2. 初始化SSL流并完成握手(因为465是SSL直连端口)
                using (SslStream sslStream = new SslStream(
                    tcpClient.GetStream(), 
                    false, 
                    ValidateServerCertificate)) // 作业场景下跳过证书验证,生产环境别这么做
                {
                    sslStream.AuthenticateAsClient(smtpServer);
                    Console.WriteLine("SSL handshake completed.");

                    // 3. 读取服务器的初始欢迎响应
                    string serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Server: {serverResponse}");

                    // 4. 发送EHLO命令(标识客户端身份,比HELO更推荐)
                    SendSmtpCommand(sslStream, $"EHLO {Dns.GetHostName()}");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"EHLO Response: {serverResponse}");

                    // 5. 执行AUTH LOGIN认证(Gmail必须)
                    SendSmtpCommand(sslStream, "AUTH LOGIN");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Auth Prompt: {serverResponse}");

                    // 发送Base64编码的邮箱地址
                    string encodedEmail = Convert.ToBase64String(Encoding.UTF8.GetBytes(senderEmail));
                    SendSmtpCommand(sslStream, encodedEmail);
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Email Auth Response: {serverResponse}");

                    // 发送Base64编码的应用专用密码
                    string encodedPassword = Convert.ToBase64String(Encoding.UTF8.GetBytes(senderPassword));
                    SendSmtpCommand(sslStream, encodedPassword);
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Password Auth Response: {serverResponse}");

                    // 6. 指定发件人
                    SendSmtpCommand(sslStream, $"MAIL FROM:<{senderEmail}>");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Mail From Response: {serverResponse}");

                    // 7. 指定收件人
                    SendSmtpCommand(sslStream, $"RCPT TO:<{recipientEmail}>");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Rcpt To Response: {serverResponse}");

                    // 8. 开始发送邮件内容
                    SendSmtpCommand(sslStream, "DATA");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Data Prompt: {serverResponse}");

                    // 构建符合RFC 5322标准的邮件内容
                    string fullEmail = $"Subject: {emailSubject}\r\n" +
                                       $"From: {senderEmail}\r\n" +
                                       $"To: {recipientEmail}\r\n" +
                                       "\r\n" + // 邮件头和正文之间必须空一行
                                       $"{emailBody}\r\n."; // 用单独一行的.结束内容

                    SendSmtpCommand(sslStream, fullEmail);
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Send Status: {serverResponse}");

                    // 9. 退出连接
                    SendSmtpCommand(sslStream, "QUIT");
                    serverResponse = ReadSmtpResponse(sslStream);
                    Console.WriteLine($"Quit Response: {serverResponse}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Oops, something went wrong: {ex.Message}");
            }
        }
    }

    // 发送SMTP命令,必须加上\r\n换行符(SMTP协议要求)
    static void SendSmtpCommand(SslStream stream, string command)
    {
        byte[] commandBytes = Encoding.UTF8.GetBytes(command + "\r\n");
        stream.Write(commandBytes, 0, commandBytes.Length);
    }

    // 读取SMTP服务器响应,处理多行响应的情况
    static string ReadSmtpResponse(SslStream stream)
    {
        StringBuilder responseBuilder = new StringBuilder();
        byte[] buffer = new byte[1024];
        int bytesRead;

        do
        {
            bytesRead = stream.Read(buffer, 0, buffer.Length);
            responseBuilder.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
        } while (stream.DataAvailable);

        return responseBuilder.ToString().Trim();
    }

    // 验证服务器证书(作业场景下直接返回true即可,生产环境要做严格校验)
    static bool ValidateServerCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors errors)
    {
        return true;
    }
}

关键注意事项(尤其是针对Gmail):

  • 应用专用密码:Gmail现在默认禁用“不太安全的应用”,所以你需要先开启两步验证,然后在Google账号的“安全”设置里生成一个应用专用密码,用这个密码代替普通登录密码。
  • SMTP命令顺序:必须严格遵循连接→EHLO→AUTH→MAIL FROM→RCPT TO→DATA→内容→.→QUIT的顺序,服务器会严格校验命令顺序。
  • 邮件格式:邮件头和正文之间必须有一个空行,正文结尾必须单独一行写.,否则服务器会认为内容还没结束。
  • 端口替代:如果465端口有问题,可以试试587端口(STARTTLS模式),这种模式下需要先发送EHLO,再发送STARTTLS命令,然后再做SSL握手。

内容的提问来源于stack exchange,提问作者Amir.S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:04:57