カスタム SQL Server Reporting Services 配信拡張機能からの電子メールの送信
-
09-06-2019 - |
質問
私は、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 から受け取ったエラー メッセージは次のとおりです。
ReportingServicesサービス!通知!4!08/28/2008-11:26:17::通知 6ab32b8d-296e-47a2-8d96-09e81222985c が完了しました。成功:偽、ステータス:例外メッセージ:メールの送信に失敗しました。スタックトレース:MyDeliveryextension.Maildelivery.sendmail(subscriptionDataデータ、Stream ReportStream、String ReportName、String SmptserverHostname、int32 smtpserverport)のC: inetpub wwwroot customReporting mydeliveryextension in c: inetpub wwwroot customReporting mydeliveryextension mydelivery.cs:行153、dearventextension:私の納品、レポート:開発をクリックして、ReportingServicEsservice!dbpolling!4!08/28/2008-11:26:17 ::NoticePolling の処理が完了しました item 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")
誰かここを手伝ってくれませんか?
解決
何があるか:
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 変数をスローしないでください。スローするだけで十分です。
この調整を試してください:
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();