为什么在发送SMTP电子邮件时出现“属性无法分配”的错误?

278

我不明白为什么这段代码无法工作。我收到一个错误,说属性无法分配

MailMessage mail = new MailMessage();
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "smtp.gmail.com";
mail.To = "user@hotmail.com"; // <-- this one
mail.From = "you@yourcompany.example";
mail.Subject = "this is a test email.";
mail.Body = "this is my test email body";
client.Send(mail);

1
请注意,如果您正在尝试通过SMTP通过Gmail发送邮件,则需要允许不安全的应用程序访问您的帐户https://support.google.com/accounts/answer/6010255?hl=en - Matthew Lock
17个回答

365

mail.Tomail.From是只读的。将它们移到构造函数中。

using System.Net.Mail;

...

MailMessage mail = new MailMessage("you@yourcompany.example", "user@hotmail.com");
SmtpClient client = new SmtpClient();
client.Port = 25;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Host = "smtp.gmail.com";
mail.Subject = "this is a test email.";
mail.Body = "this is my test email body";
client.Send(mail);

9
邮件地址集合的"To"属性是只读的,而"From"属性则不是。 该属性为MailAddressCollection类型,可获取该集合中所有邮件地址的列表。 - MRB
41
因为它是一个集合,你可以直接调用add方法将元素添加进去。 - Oskar Kjellin
17
@Oskar 好的,我应该更具体一些。您无法将mail.to设置为特定地址。您必须使用构造函数或调用add。我只是在处理第一个编译器警告:错误CS0200:属性或索引器“System.Net.Mail.MailMessage.To”无法分配--它是只读的。 - MRB
9
您可以使用 SmtpClient 类与密码保护的 SMTP 服务器。您的 SMTP 服务器似乎是内部服务器,这意味着当程序在网络上时,它只能连接到该 SMTP 服务器。client.Host = "mail.youroutgoingsmtpserver.com";client.Credentials = new System.Net.NetworkCredential("yourusername", "yourpassword"); - clifford.duke
4
SmtpClient实现了IDisposable接口,因此你可能需要将其更改为:using (SmtpClient client = new SmtpClient()) { ... } - Mark Miller
显示剩余9条评论

261

这个:

mail.To = "user@hotmail.com";

应该是:

mail.To.Add(new MailAddress("user@hotmail.com"));

使用此方法和默认的 MailMessage 构造函数,您可以设置 To 字段而不设置 From 字段,后者将默认为 <smtp> 元素(网络设置) 中的值。 - bstoney
有人能告诉我如何使它适用于我的 SMTP 服务器,而不是谷歌 SMTP 吗?当我尝试连接到我的 SMTP 服务器时,我收到{"无法连接到远程服务器"} {"请求的地址在其上下文中无效 IP-ADDRESS:25"}错误。 - YuDroid
@YuDroid 请正确设置 SmtpClientHostPort 属性。 - Mithrandir
@Mithrandir 是的,我正在正确设置它。我已经在Outlook中设置了我的SMTP邮件帐户,并从那里获取了所有必要的设置。主机和端口在Web.config文件中声明,我正在运行时获取它。 - YuDroid

121

终于搞定了 :)

using System.Net.Mail;
using System.Text;

...

// Command line argument must the the SMTP host.
SmtpClient client = new SmtpClient();
client.Port = 587;
client.Host = "smtp.gmail.com";
client.EnableSsl = true;
client.Timeout = 10000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("user@gmail.com","password");

MailMessage mm = new MailMessage("donotreply@domain.example", "sendtomyemail@domain.example", "test", "test");
mm.BodyEncoding = UTF8Encoding.UTF8;
mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

client.Send(mm);

之前的拼写糟糕,很抱歉。


5
难道不应该有一个 mm.Dispose() 吗? - Steam
顺便说一下,默认的SMTP端口是25。 - Steam
@Steam 那个时候默认的 SMTP 端口是 587。 - Sam Stephenson
2
谢谢!即使到今天为止,它仍然可以工作,但是使用Outlook。[client.Host = "smtp-mail.outlook.com";] - compski
6
587是安全的SMTP。 - Peter
1
@freej17 添加邮件地址副本 = new MailAddress("Notification_List@contoso.com"); mm.CC.Add(副本); - Sam Stephenson

19
public static void SendMail(MailMessage Message)
{
    SmtpClient client = new SmtpClient();
    client.Host = "smtp.googlemail.com";
    client.Port = 587;
    client.UseDefaultCredentials = false;
    client.DeliveryMethod = SmtpDeliveryMethod.Network;
    client.EnableSsl = true;
    client.Credentials = new NetworkCredential("myemail@gmail.com", "password");
    client.Send(Message); 
}

4
这根本没有解决为什么OP无法对MailMessage属性进行赋值的问题。 - ProfK

17

这是我的方法,希望你觉得有用。

MailMessage objeto_mail = new MailMessage();
SmtpClient client = new SmtpClient();
client.Port = 25;
client.Host = "smtp.internal.mycompany.com";
client.Timeout = 10000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("user", "Password");
objeto_mail.From = new MailAddress("from@server.com");
objeto_mail.To.Add(new MailAddress("to@server.com"));
objeto_mail.Subject = "Password Recover";
objeto_mail.Body = "Message";
client.Send(objeto_mail);

13

首先前往https://myaccount.google.com/lesssecureapps,并将“允许安全性较低的应用程序”设置为true

然后使用以下代码。此代码仅适用于您发件人地址为 Gmail 的情况。

static void SendEmail()
    {
        string mailBodyhtml =
            "<p>some text here</p>";
        var msg = new MailMessage("from@gmail.com", "to1@gmail.com", "Hello", mailBodyhtml);
        msg.To.Add("to2@gmail.com");
        msg.IsBodyHtml = true;
        var smtpClient = new SmtpClient("smtp.gmail.com", 587); //**if your from email address is "from@hotmail.com" then host should be "smtp.hotmail.com"**
        smtpClient.UseDefaultCredentials = true;
        smtpClient.Credentials = new NetworkCredential("from@gmail.com", "password");
        smtpClient.EnableSsl = true;
        smtpClient.Send(msg);
        Console.WriteLine("Email Sent Successfully");
    }

7
如果您不想在代码中显示您的电子邮件和密码,并希望您的公司电子邮件客户端服务器使用您的Windows凭据,请使用以下方法。
client.Credentials = CredentialCache.DefaultNetworkCredentials;

Source


这与client.UseDefaultCredentials = true;相同。 - Alexander

4
这个方法在2017年3月对我有效。起初,按照上面“终于可用:)”的解决方案没有成功。请参考以下内容:
SmtpClient client = new SmtpClient();
client.Port =  587;
client.Host = "smtp.gmail.com";
client.EnableSsl = true;
client.Timeout = 10000;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("<me>@gmail.com", "<my pw>");
MailMessage mm = new MailMessage(from_addr_text, to_addr_text, msg_subject, msg_body);
mm.BodyEncoding = UTF8Encoding.UTF8;
mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

client.Send(mm);

3
这篇回答涉及以下内容: 这是提取出来的代码:
    public async Task SendAsync(string subject, string body, string to)
    {
        using (var message = new MailMessage(smtpConfig.FromAddress, to)
        {
            Subject = subject,
            Body = body,
            IsBodyHtml = true
        })
        {
            using (var client = new SmtpClient()
            {
                Port = smtpConfig.Port,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Host = smtpConfig.Host,
                Credentials = new NetworkCredential(smtpConfig.User, smtpConfig.Password),
            })
            {
                await client.SendMailAsync(message);
            }
        }                                     
    }

类 SmtpConfig:

public class SmtpConfig
{
    public string Host { get; set; }
    public string User { get; set; }
    public string Password { get; set; }
    public int Port { get; set; }
    public string FromAddress { get; set; }
}

2
MailMessage mm = new MailMessage(txtEmail.Text, txtTo.Text);
mm.Subject = txtSubject.Text;
mm.Body = txtBody.Text;
if (fuAttachment.HasFile)//file upload select or not
{
    string FileName = Path.GetFileName(fuAttachment.PostedFile.FileName);
    mm.Attachments.Add(new Attachment(fuAttachment.PostedFile.InputStream, FileName));
}
mm.IsBodyHtml = false;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.EnableSsl = true;
NetworkCredential NetworkCred = new NetworkCredential(txtEmail.Text, txtPassword.Text);
smtp.UseDefaultCredentials = true;
smtp.Credentials = NetworkCred;
smtp.Port = 587;
smtp.Send(mm);
Response.write("Send Mail");

观看视频: https://www.youtube.com/watch?v=bUUNv-19QAI

(注:此处无需翻译,仅为格式说明)

虽然这个视频可能会回答问题,但最好在此处包括答案的关键部分并提供参考链接。仅提供链接的答案可能会因链接页面的更改而失效。 - afxentios
msdn 中对于 UseDefaultCredentials 属性说明: 如果将 UseDefaultCredentials 属性设置为 false,则会使用 Credentials 属性中设置的值作为连接到服务器时的凭据。因此,如果您使用了 Credentials 属性(自定义凭据),则应将 UseDefaultCredentials 属性设置为 false。 - Sergei Iashin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接