Отправка электронной почты из настраиваемого расширения доставки служб SQL Server Reporting Services

Я разработал собственное расширение доставки для Reporting Services 2005, чтобы интегрировать его с нашим маркетинговым решением SaaS.

Он принимает подписку и делает снимок отчета с настраиваемым набором параметров. Затем он отображает отчет, отправляет электронное письмо со ссылкой и прикрепленным отчетом в формате XLS.

Все работает нормально, до доставки почты ...

Вот мой код для отправки электронной почты:

 public static List<string> SendMail(SubscriptionData data, Stream reportStream, string reportName, string smptServerHostname, int smtpServerPort)
{
  List<string> failedRecipients = new List<string>();

  MailMessage emailMessage = new MailMessage(data.ReplyTo, data.To);
  emailMessage.Priority = data.Priority;
  emailMessage.Subject = data.Subject;
  emailMessage.IsBodyHtml = false;
  emailMessage.Body = data.Comment;

  if (reportStream != null)
  {
    Attachment reportAttachment = new Attachment(reportStream, reportName);
    emailMessage.Attachments.Add(reportAttachment);
    reportStream.Dispose();
  }

  try
  {
    SmtpClient smtp = new SmtpClient(smptServerHostname, smtpServerPort);

    // Send the MailMessage
    smtp.Send(emailMessage);
  }
  catch (SmtpFailedRecipientsException ex)
  {
    // Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
    failedRecipients.Add(ex.FailedRecipient);
  }
  catch (SmtpFailedRecipientException ex)
  {
    // Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
    failedRecipients.Add(ex.FailedRecipient);
  }
  catch (SmtpException ex)
  {
    throw ex;
  }
  catch (Exception ex)
  {
    throw ex;
  }

  // Return the List of failed recipient e-mail addresses, so the client can maintain its list.
  return failedRecipients;
}

Значения для SmtpServerHostname - localhost, а порт - 25.

Я убедился, что действительно могу отправлять почту с помощью Telnet. И это работает.

Вот сообщение об ошибке, которое я получаю от SSRS:

ReportingServicesService! Notification! 4! 28.08.2008-11: 26: 17 :: Уведомление 6ab32b8d-296e-47a2-8d96-09e81222985c завершено. Успех: Ложь, Статус: Сообщение об исключении: Ошибка отправки почты. Stacktrace: в MyDeliveryExtension.MailDelivery.SendMail (данные SubscriptionData, Stream reportStream, String reportName, String smptServerHostname, Int32 smtpServerPort) в C: \ inetpub \ wwwroot \ CustomReporting \ MyDeliveryExtension \ MailDelivery.cs: строка 48 в MyDeliveryExtension.MyDelivery.Deliver (уведомление об уведомлении) в C: \ inetpub \ wwwroot \ CustomReporting \ MyDeliveryExtension \ MyDelivery.cs: строка 153, DeliveryExtension: Моя доставка, Отчет: Разработка кликов, Попытка 1 ReportingServicesService! Dbpolling! 4! 28.08.2008-11: 26: 17 :: NotificationPolling завершил обработку элемента 6ab32b8d-296e-47a2-8d96-09e81222985c

Может ли это иметь какое-то отношение к Trust / Code Access Security?

Моему расширению доставки предоставлено полное доверие к rssrvpolicy.config:

   <CodeGroup 
    class = "UnionCodeGroup"
    version = "1"
    PermissionSetName = "FullTrust"
    Name = "MyDelivery_CodeGroup"
    Description = "Code group for MyDelivery extension">
    <IMembershipCondition class = "UrlMembershipCondition" version = "1" Url = "C:\Program Files\Microsoft SQL Server\MSSQL.2\Reporting Services\ReportServer\bin\MyDeliveryExtension.dll" />
   </CodeGroup> 

Может ли доверие быть здесь проблемой?

Другая теория: SQL Server и SSRS были установлены в контексте безопасности локальной системы. Я прав, или у этой учетной записи службы ограничен доступ к какому-либо сетевому ресурсу? Даже собственный SMTP-сервер?

Я попытался изменить все учетные записи служб SQL Server на администратора, но все равно безуспешно.

Я также попытался войти на SMTP-сервер в своем коде, указав: NetworkCredential («Администратор», «пароль»), а также NetworkCredential («Администратор», «пароль», «MyRepServer»).

Кто-нибудь может здесь помочь, пожалуйста?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
6 788
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Что на:

at MyDeliveryExtension.MailDelivery.SendMail(SubscriptionData data, Stream reportStream, String reportName, String smptServerHostname, Int32 smtpServerPort) 
  in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MailDelivery.cs:line 48 

at MyDeliveryExtension.MyDelivery.Deliver(Notification notification) 
  in C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MyDelivery.cs:line 153

Также кажется, что вы удаляете поток отчета, но это должно выполняться тем, что открывало этот поток, а не вашим методом (не будет очевидно, что присоединение потока удаляет его).

Вы теряете часть трассировки стека из-за того, как вы повторно генерируете исключения. Не бросайте переменную ex, достаточно просто throw.

Попробуйте эту настройку:

public static List<string> SendMail(SubscriptionData data, Stream reportStream, string reportName, string smptServerHostname, int smtpServerPort)
{
  List<string> failedRecipients = new List<string>();

  MailMessage emailMessage = new MailMessage(data.ReplyTo, data.To) {
      Priority = data.Priority,
      Subject = data.Subject,
      IsBodyHtml = false,
      Body = data.Comment
  };

  if (reportStream != null)
    emailMessage.Attachments.Add(new Attachment(reportStream, reportName));

  try
  {
      SmtpClient smtp = new SmtpClient(smptServerHostname, smtpServerPort);

      // Send the MailMessage
      smtp.Send(emailMessage);
  }
  catch (SmtpFailedRecipientsException ex)
  {
    // Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
    failedRecipients.Add(ex.FailedRecipient);

    //are you missing a loop here? only one failed address will ever be returned
  }
  catch (SmtpFailedRecipientException ex)
  {
    // Delivery failed for the recipient. Add the e-mail address to the failedRecipients List
    failedRecipients.Add(ex.FailedRecipient);
  }

  // Return the List of failed recipient e-mail addresses, so the client can maintain its list.
  return failedRecipients;
}

Я попытался удалить вложение reportStream:

  //if (reportStream != null)    
     //emailMessage.Attachments.Add(new Attachment(reportStream, reportName));

И теперь работает нормально.

Так что это как-то связано с reportStream.

После того, как я пошутил с настройкой, которая получает reportStream, я смог исправить проблему с отправкой почты.

Ошибка была не в методе SendMail, а где-то еще. Однако исключение было выдано в контексте SendMail. Ошибка!

Вот почему вам следует избегать:

catch (Exception ex)
{
    throw ex;
}

Поскольку это в основном скрывает ваше исключение в новом.

Если вы используете:

catch (Exception ex)
{
    throw; //note: no ex
}

Он сохраняет исходное исключение и трассировку стека.

FileStream m_fileStream = null;

m_files = notification.Report.Render(format, null);
RenderedOutputFile m_renderedOutputFile = m_files[0];
m_fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
m_renderedOutputFile.Data.Seek((long)0, SeekOrigin.Begin);
byte[] arr = new byte[(int)m_renderedOutputFile.Data.Length + 1];

m_renderedOutputFile.Data.Read(arr, 0, (int)m_renderedOutputFile.Data.Length);

m_fileStream.Write(arr, 0, (int)m_renderedOutputFile.Data.Length);

m_fileStream.Close();

Другие вопросы по теме