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索引越界)
修改方案
- 处理单元格空值:调用
ToString()前先判断值是否为null - 修正m_Path赋值位置:仅在用户确认保存时才赋值
m_Path - 校验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客户端访问
修改方案
- 调整认证设置顺序:先禁用默认凭证,再设置自定义凭证
- 适配MFA:若账号开启MFA,生成并使用应用密码
- 更新SMTP服务器地址:使用官方推荐的
smtp.office365.com - 添加资源释放与异常处理:使用
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
相关产品推荐
相关产品推荐

