Отправка электронной почты с помощью С# - не работает, но ошибка не возникает

как следует из названия темы, я пытаюсь отправить электронное письмо из своего приложения на С#, и у меня возникают небольшие проблемы.

Я написал функцию ниже, чтобы упростить отправку почты из моего приложения, но я считаю, что где-то должна быть проблема, и я просто не вижу ее. Возможно, это сценарий «За деревьями не видно леса».

Проблема возникает, когда я пытаюсь отправить электронную почту через SMTP. Кажется, что страница просто истекает по тайм-ауту, без сообщения об ошибке. LocalPickup работает, как и указание каталога для раскладки, но в этом случае мне нужно использовать SMTP.

В этом случае мой веб-сайт расположен на моем домашнем сервере разработки (под управлением Windows Server 2003), а мой SMTP-сервер представляет собой удаленный выделенный ящик, на котором работает CentOS Linux с Qmail.

Я включил функцию, которую написал, и просто для того, чтобы ответить на любые вопросы. Да, порт SMTP на этом сервере определенно 26 ;)

    /// <summary>
    /// Sends an email
    /// </summary>
    /// <param name="To">Addresses to send the email to, comma seperated</param>
    /// <param name="subject">Subject of the email</param>
    /// <param name="emailBody">Content of the email</param>
    /// <param name="cc">CC addresses, comma seperated [Optional]</param>
    /// <param name="Bcc">BCC addresses, comma seperated [Optional]</param>
    /// <param name="client">How to send mail, choices: iis, network, directory. [Optional] Defaults to iis</param>
    /// <returns></returns>
    public bool sendMail(string To, string subject, string emailBody, string from, string cc = "", string Bcc = "", string client = "network", bool html = true)
    {

        // Create a mailMessage object
        MailMessage objEmail = new MailMessage();
        objEmail.From = new MailAddress(from);
        // Split email addresses by comma
        string[] emailTo = To.Split(',');
        foreach (string address in emailTo)
        {
            // Add these to the "To" address
            objEmail.To.Add(address);
        }

        // Check for CC addresses

        if (cc != "")
        {
            string[] emailCC = cc.Split(',');
            foreach (string addressCC in emailCC)
            {
                objEmail.CC.Add(addressCC);
            }
        }

        // Check for Bcc addresses

        if (Bcc != "")
        {
            string[] emailBCC = Bcc.Split(',');
            foreach (string addressBCC in emailBCC)
            {
                objEmail.Bcc.Add(addressBCC);
            }
        }

        // Set the subject.
        objEmail.Subject = subject;

        // Set the email body
        objEmail.Body = emailBody;

        // Set up the SMTP client

        SmtpClient server = new SmtpClient();


        switch (client)
        {
            case "iis":
                server.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
                break;
            case "network":
                server.DeliveryMethod = SmtpDeliveryMethod.Network;
                NetworkCredential credentials = new NetworkCredential("SmtpUserName", "SmtpPassword");
                server.Host = "SmtpHost";
                server.Port = 26;
                server.Credentials = credentials;
                break;
            case "directory":
                server.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory;
                server.PickupDirectoryLocation = "c:\\mailpickup";
                break;
            default:
                throw new Exception("Invalid delivery method specified, cannot continue!");

        }

        if (html)
        {
            // As the email is HTML, we need to strip out all tags for the plaintext version of the email.
            string s = emailBody;

            s = Regex.Replace(s, "<.*?>", string.Empty);
            s = Regex.Replace(s, "<script.*?</script>", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);

            AlternateView plainText = AlternateView.CreateAlternateViewFromString(s, null, MediaTypeNames.Text.Plain);
            objEmail.AlternateViews.Add(plainText);

            AlternateView rich = AlternateView.CreateAlternateViewFromString(emailBody, null, MediaTypeNames.Text.Html);
            objEmail.AlternateViews.Add(rich);
        }


        try
        {
            server.Send(objEmail);
            return true;
        }
        catch(Exception ex)
        {
            throw new Exception(ex.ToString());
        }

Как я уже сказал, страница полностью зависает примерно через 60 секунд, и сообщение об ошибке не отображается.

Заранее спасибо,

Дэйв

Дополнение: - Вот как я вызываю sendMail()

webMail sendConfirmation = new webMail();

fileSystem fs = new fileSystem();
siteSettings setting = new siteSettings();
string mailBody = fs.file_get_contents("http://myurl.com/mymessage.html");

// Run any replaces.
mailBody = mailBody.Replace("{EMAIL_TITLE}", "Your account requires confirmation");
mailBody = mailBody.Replace("{U_FNAME}", u_forename);
mailBody = mailBody.Replace("{REG_URL_STRING}", setting.confirmUrl);


sendConfirmation.sendMail(u_emailAddress, "Your account requires confirmation", mailBody, setting.siteEmail);

person Dave    schedule 15.03.2011    source источник
comment
Вряд ли проблема с кодом. Используйте telnet для удаленного подключения к SMTP и проверьте support.microsoft.com/kb/153119.   -  person P.Brian.Mackey    schedule 16.03.2011
comment
Это много кода, я предлагаю использовать точки останова.   -  person The Muffin Man    schedule 16.03.2011
comment
Можете ли вы отладить его и посмотреть, выдает ли он какие-либо исключения?   -  person OrahSoft    schedule 16.03.2011
comment
Хорошо, мне удалось заставить работать локальную отладку на моей машине, и на самом деле возникло исключение. Исключение: синтаксическая ошибка, команда не распознана. Ответ сервера: извините, не удается найти действительный MX для домена rcpt.   -  person Dave    schedule 16.03.2011
comment
@P.Brian.Mackey - Telnet к моему почтовому серверу работал без проблем. Я получил тестовое сообщение и т.д.   -  person Dave    schedule 16.03.2011


Ответы (6)


не удается найти допустимый MX для домена rcpt, как правило, означает, что не удается найти действительный адрес электронной почты или домен электронной почты для ретрансляции электронной почты: я бы взглянул на массив адресов электронной почты «кому», разделенных, чтобы убедиться, что каждый из них действителен /с действительного домена. Возможно, отправьте один тест на каждый адрес электронной почты «кому», чтобы вы могли проверить, не является ли это проблемой smtp-сервера.

Другая возможность - разрешения localhost/iis для ретрансляции на другой smtp-сервер "??"

Мой тестовый код для одноадресных тестов:

public void Send(string from, string to,string smtpServer, int smtpPort,string username, string password)
        {
            try
            {
                using (MailMessage mm = new MailMessage())
                {
                    SmtpClient sc = new SmtpClient();
                    mm.From = new MailAddress(from, "Test");
                    mm.To.Add(new MailAddress(to));
                    mm.IsBodyHtml = true;
                    mm.Subject = "Test Message";
                    mm.Body = "This is a test email message from csharp";
                    mm.BodyEncoding = System.Text.Encoding.UTF8;
                    mm.SubjectEncoding = System.Text.Encoding.UTF8;
                    NetworkCredential su = new NetworkCredential(username, password);
                    sc.Host = smtpServer;
                    sc.Port = smtpPort;
                    sc.Credentials = su;
                    sc.Send(mm);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
person justinlabenne    schedule 16.03.2011

вы можете попробовать проверить на ошибку:

SmtpClient smtp = new SmtpClient();
            smtp.SendCompleted += new SendCompletedEventHandler(smtp_SendCompleted);
            smtp.Send(msgMail);

void smtp_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
    {
        if (e.Cancelled == true || e.Error != null)
        {
            throw new Exception(e.Cancelled ? "EMail sedning was canceled." : "Error: " + e.Error.ToString());
        }
person Robert    schedule 15.03.2011
comment
Мероприятие SendCompleted() мне очень помогло. Свойство e.Error также имеет трассировку стека, что было важно для меня. - person mihkov; 19.11.2019
comment
Какую магию вы использовали, чтобы заставить его работать? Я пробовал это, и событие Send_Completed никогда не вызывается, а также не на компьютере, на котором отправляется почта. - person GuidoG; 25.11.2020

Для моей компании причина, по которой у нас возникла эта проблема, заключалась в том, что сервер или машина, которая отправляла электронные письма, не были включены в белый список почтового сервера. Как только IP-адрес машины был внесен в белый список, он начал работать. По той же причине вы можете проверить черный список почтовых серверов.

person goku_da_master    schedule 01.12.2014

Иногда письма, отправленные таким образом, попадают в спам, особенно если адрес отправителя вымышленный. Попробовать необработанный ftp с помощью telnet, как сказал вам P.Brian.Macket, это хорошая идея.

person Felice Pollano    schedule 15.03.2011

ваш клиент по умолчанию использует сеть, но когда вы определяете сетевой клиент, вы используете некоторый код по умолчанию (имя пользователя, пароль хоста).

 case "network":
            server.DeliveryMethod = SmtpDeliveryMethod.Network;
            NetworkCredential credentials = new NetworkCredential("SmtpUserName", "SmtpPassword");
            server.Host = "SmtpHost";
            server.Port = 26;
            server.Credentials = credentials;
            break;

Я действительно думаю, что вы используете пример кода и забыли указать свою пользовательскую конфигурацию.

Прошу прощения за мой английский.

person fdaines    schedule 15.03.2011
comment
Это определенно не пример кода :) - я написал это сам для чего-то в работе, но он никогда не тестировался для SMTP, только для IIS Local Pickup. - person Dave; 16.03.2011
comment
можете ли вы прикрепить пример вызова к public bool sendMail(..), возможно, проблема заключается в параметре To, вы делаете Split по параметру To - person fdaines; 16.03.2011
comment
Я добавил свой вызов sendMail() в свой первый пост — я думаю, что мы исключили параметр To как проблему. Ошибка теперь фактически отображается и заявляет, что нет действительной записи MX - хотя, определенно, есть. Я использую этот почтовый сервер каждый день. - person Dave; 16.03.2011
comment
Возможно, в u_emailAddress есть одна поврежденная запись электронной почты, проверьте ее (возможно, журнал в цикле foreach). Я думаю, что когда вы отправляете сообщение на множество электронных писем, почтовый сервер должен проверять их все. Я действительно не знаю, что произойдет, если одно электронное письмо будет плохим, возможно, сообщение не будет отправлено. - person fdaines; 16.03.2011

Является ли «Кому» зарезервированным словом в С#? Попробуйте изменить это и посмотреть, что вы получите тогда.

person MAW74656    schedule 15.03.2011
comment
Это действительно очень хороший момент. - Поменял на mailTo, но все равно с той же ошибкой. Спасибо - person Dave; 16.03.2011