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

WinForms程序SMTP发送带Excel附件邮件失败问题求助

WinForms应用两个问题的解决方案

问题1:空引用异常及m_Path未更新

问题分析

  • 空引用异常核心原因是dataGridView1.Rows[i].Cells[imeiCol].Value.ToString():当单元格值为null时,直接调用ToString()会触发空引用错误
  • m_Path赋值在SaveFileDialog的确认分支外,若用户取消保存,sfd.FileName为空,导致m_Path无效,后续无法添加附件
  • 未校验imeiCol是否找到(返回-1时会导致Cells索引越界)

修改方案

  1. 处理单元格空值:调用ToString()前先判断值是否为null
  2. 修正m_Path赋值位置:仅在用户确认保存时才赋值m_Path
  3. 校验IMEI列索引有效性:避免越界访问

修改后的关键代码片段

// 先校验imeiCol是否有效
int imeiCol = Array.FindIndex(dgvColumnNames, t => t.Split(',').Contains(imeiColName));
if (imeiCol == -1)
{
    MessageBox.Show("未找到IMEI列,请检查列名配置");
    return;
}

// ... 其他代码 ...

// 写入IMEI时处理空值
try
{
    for (int i = 0; i < dataGridView1.Rows.Count; i++)
    {
        var cellValue = dataGridView1.Rows[i].Cells[imeiCol].Value;
        // 空值时赋值空字符串,避免空引用
        worksheet.Cells[i + 2, 4] = cellValue != null ? cellValue.ToString() : string.Empty;
    }
}
catch (Exception ex)
{
    MessageBox.Show("写入IMEI时出错:" + ex.Message);
}

// ... 保存文件部分 ...
try
{
    SaveFileDialog sfd = new SaveFileDialog();
    sfd.Filter = "Excel (*.xlsx)|*.xlsx";
    sfd.FileName = setFileName("name");
    sfd.DefaultExt = ".xlsx";
    if (sfd.ShowDialog() == DialogResult.OK)
    {
        workbook.SaveAs(sfd.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
        // 仅在保存成功时赋值m_Path
        m_Path = sfd.FileName;
    }
}
catch (Exception ex)
{
    MessageBox.Show("保存文件出错:" + ex.Message);
}

问题2:SMTP邮件认证失败

问题分析

  • Office365 SMTP认证失败常见原因:
    • UseDefaultCredentials和Credentials的设置顺序错误(必须先设为false,再赋值Credentials)
    • 账号开启了多重身份验证(MFA),需使用应用密码而非普通密码
    • 服务器地址使用旧的smtp-legacy.office365.com,推荐使用官方标准地址smtp.office365.com
    • 组织邮箱策略限制了SMTP客户端访问

修改方案

  1. 调整认证设置顺序:先禁用默认凭证,再设置自定义凭证
  2. 适配MFA:若账号开启MFA,生成并使用应用密码
  3. 更新SMTP服务器地址:使用官方推荐的smtp.office365.com
  4. 添加资源释放与异常处理:使用using语句自动释放邮件客户端资源

修改后的sendEmail代码

private void sendEmail(string destMail, string subject, string body, string[] attachmentPath)
{
    // 使用using语句自动释放资源,避免内存泄漏
    using (SmtpClient mailServer = new SmtpClient("smtp.office365.com", 587))
    using (MailMessage msg = new MailMessage("email@outlook.com", destMail))
    {
        mailServer.EnableSsl = true;
        // 先禁用默认凭证,再设置自定义凭证,顺序不能反
        mailServer.UseDefaultCredentials = false;
        // 若开启MFA,替换为Microsoft账户中心生成的应用密码
        mailServer.Credentials = new System.Net.NetworkCredential("email@outlook.com", "你的邮箱密码/应用密码");
        
        msg.Subject = subject;
        msg.Body = body;
        
        // 添加附件前检查文件是否存在,避免无效路径报错
        foreach (string file in attachmentPath)
        {
            if (!string.IsNullOrEmpty(file) && File.Exists(file))
            {
                msg.Attachments.Add(new Attachment(file));
            }
        }
        
        try
        {
            mailServer.Send(msg);
            MessageBox.Show("邮件发送成功");
        }
        catch (Exception ex)
        {
            MessageBox.Show("邮件发送失败:" + ex.Message);
        }
    }
}

额外注意事项

  • 应用密码需登录Microsoft账户中心生成(路径:账户安全 > 高级安全选项 > 应用密码)
  • 若使用企业邮箱,需联系IT管理员确认是否允许SMTP客户端访问

内容的提问来源于stack exchange,提问作者Ellak123

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 02:06:31