【问题标题】:Sending e-mail from a Custom SQL Server Reporting Services Delivery Extension从自定义 SQL Server Reporting Services Delivery Extension 发送电子邮件
【发布时间】:2008-08-28 09:50:48
【问题描述】:

我为 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!08/28/2008-11:26:17:: 通知 6ab32b8d-296e-47a2-8d96-09e81222985c 已完成。成功:False,状态:异常消息:发送邮件失败。 Stacktrace:在 C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MailDelivery.cs: 中的 MyDeliveryExtension.MailDelivery.SendMail(SubscriptionData data, Stream reportStream, String reportName, String smptServerHostname, Int32 smtpServerPort) 在 C:\inetpub\wwwroot\CustomReporting\MyDeliveryExtension\MyDelivery.cs:line 153 中的 MyDeliveryExtension.MyDelivery.Deliver(通知通知),DeliveryExtension:我的交付,报告:点击开发,尝试 1 ReportingServicesService!dbpolling!4!08/28/2008-11:26:17:: NotificationPolling完成处理项6ab32b8d-296e-47a2-8d96-09e81222985c

这可能与信任/代码访问安全有关吗?

我的交付扩展被授予对 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("Administrator", "password") 和 NetworkCredential("Administrator", "password", "MyRepServer")

有人可以帮忙吗?

【问题讨论】:

    标签: c# reporting-services


    【解决方案1】:

    在什么地方:

    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;
    }
    

    【讨论】:

      【解决方案2】:

      我试图删除 reportStream 附件:

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

      现在它可以正常工作了。

      所以它与reportStream有关。

      【讨论】:

        【解决方案3】:

        在玩弄了获取reportStream的功能之后,我能够解决邮件发送问题。

        错误不在 SendMail 方法中,而是在其他地方。异常是在 SendMail 的上下文中引发的。搞砸了!

        【讨论】:

          【解决方案4】:

          这就是为什么你必须避免:

          catch (Exception ex)
          {
              throw ex;
          }
          

          因为这基本上将您的异常隐藏在一个新异常中。

          如果你使用:

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

          它保留原始异常和堆栈跟踪。

          【讨论】:

            【解决方案5】:
            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();
            

            【讨论】:

              猜你喜欢
              • 2023-04-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多