送信済Mailを編集して送信した再送Mailを回収(Recall)する -3-
<話題の履歴>
送信済Mailを編集して送信した再送Mailを回収(Recall)する -2-
送信済Mailを編集して送信した再送Mailを回収(Recall)する -1-
前回は、送信済Mail再送時のRecallの問題の原因と問題を解消するための解決策を考えてみました。
今回は、実際にUNIDを変更して送信する解決策を試してみます。
LotusScriptでは、Document.UniversalID PropertyでUNIDの取得と変更が許されているのは皆さんご存知だとは思いますが、UNIDを変更してMailを送信するためには、まずUNIDは生成できるのか?から考えないといけません。
まず、UNIDとはどういうものなのかを調べてみます。
Technoteによると、以下の構成になっています。
typedef struct {
DBID File; /* Unique (random) number */
/* (Even though this field is called "File," */
/* it doesn't have anything to do with the file!) */
TIMEDATE Note; /* Original Note Creation time/date */
} UNIVERSALNOTEID;
#define UNID UNIVERSALNOTEID
上記の記述だけでは分かりませんが、C-APIのManualやTechnoteを参照すれば分かりますが、UNIDは32文字の構成ですが、最初の16文字がランダムなDBID、残りの16文字が日付から生成される固有値という構成なのです。
Technoteでは、LotusScriptでUNIDを生成する方法を提示していますが、今回はもう少し簡易な方法を取ってみたいと思います。
UNIDの後半の16文字は日付から生成されており、以前、このBlogで紹介した「【非公開関数】Replica IDの計算 ?」を参照頂くと分かりますが、非公開関数を使って生成することが可能となっています。
UNIDの前半はランダムな16文字となっていますが、日時から生成される後半16文字はMail DBの文書であれば、同一日時はほぼあり得ない(Mail DBは基本的に利用者は一人で、代理人が使ったとしてもほぼ一致することはない)ため、送信済MailのUNIDの最初の16文字と日時から計算した16文字を使って生成することにします。
Mail DBのMessage(Memo) FormをCustomizeして、今回の回避策を実装してみることにします。
実際には、ReplyなどのFormの変更も必要ですし、LotusScript Lib.のcMemoObject.QuerySend()を修正した方が良いかもわかりませんが、今回は実験なので、Message(Memo) Formのみを修正して試します。
Message(Memo) FormのQuerySend Eventに以下を追記します(Mail TemplateはV10の物を利用しています)。
Sub Querysend(Source As Notesuidocument, Continue As Variant)
If source.InPreviewPane Then Exit Sub
If cMemoObject Is Nothing Then Exit Sub
Call cMemoObject.QuerySend()
'Check preference and Warn if subject is blank for a new memo
If (cMemoObject.tmpOnSendEnabled = False) Then
If source.Document.EnableBlankSubject(0) <> "1" Then
If source.document.Subject(0) = "" Then
If Messagebox(warnTxt, MB_YESNO + MB_ICONQUESTION, warnTitle ) = IDNO Then
vSubjectBlankSend = False
Source.GoToField("Subject")
Call source.Refresh
If cMemoObject.GetActionInProgress = MEMO_ACTION_NONE Then
Call source.Save
Else
Call cMemoObject.SetActionInProgress(MEMO_ACTION_NONE)
Call Source.Document.ReplaceItemValue("SaveOptions","0")
End If
cMemoObject. SendBlankSubject=False
continue = False
Exit Sub
Else
vSubjectBlankSend = True
cMemoObject. SendBlankSubject=True
End If
End If
End If
Else
If cMemoObject.tmpBlockOnSend=True Then
continue = False
If cMemoObject.GetActionInProgress = MEMO_ACTION_NONE Then
Call source.Save
Else
Call cMemoObject.SetActionInProgress(MEMO_ACTION_NONE)
Call Source.Document.ReplaceItemValue("SaveOptions","0")
End If
If (cMemoObject.SendBlankSubject=False) Then
vSubjectBlankSend = False
Source.GoToField("Subject")
Else
vSubjectBlankSend = True
Source.GoToField("Body")
End If
Exit Sub
End If
End If
If source.Document.HasItem("ActionInProgress") Then
source.Document.RemoveItem("ActionInProgress")
End If
'If message is already sent, change DocumentUNID for recall
If source.Document.HasItem("PostedDate") Then
Dim unid As String
Dim ret As Variant
ret = Evaluate(|@Text(@Now;"*")|)
unid = Left(source.Document.UniversalID,16) + Replace(ret(0), ":","")
source.Document.UniversalID = unid
End If
End Sub
まず、文書が既に送信済文書であるかどうかをPostedDateが存在するかどうかで判断し、非公開関数を使ってUNIDの後半16桁を計算し、元の送信済MailのUNIDの前半16桁を利用してUNIDを設定するという非常に単純なCodeです。
非公開関数は、8桁で":"で区切られた値が返ってきますので取り除いています。
このCustomizeを施したMail DBで最初に検証したのと同様にテストしていきます。
新規にMailを作成し送信した後に、送信済Mailを編集して再送すると、UNIDが異なるため、別の文書として送信済Viewに表示されるようになります。
ここで、送信済Mailを編集送信した2番目のMailをRecallします。
以下のように正常にRecallが完了したことが確認できます。
受信者のMailにも、2番目のMailは存在しないことが分かります。
勿論、1番目のMailをRecallしても、正常にRecallが行われます。
UNIDを変更しているので当たり前の結果です。
Message Recallの仕組みはRouterで処理するため、メーカーはUNIDで特定しているので修正は困難であり、「製品の制限」と言うのかも知れませんが、Mail Templateに少し手を加えてやることで解決できるのです。
ここで紹介した解決策はあくまでSampleですので、本番環境で実装される場合は変更部分を詳細に検討した上で十分にテストしてください。
今回は、Memo Formのみの修正ですが、返信Mailでも同様に再送MailのRecallの必要があるのであれば、QuerySendで処理する限りは、Reply Formについても対応が必要と考えます(Reply with History & Attachments FormはAliasがReplyなので再送MailのFormはReplyなので対応は不要と考えます)。
個人的には、メーカーが正式に実装してくれることを望んでいます。
今回は、実際にUNIDを変更して送信する解決策を試してみました。
次回は、少し話題から逸れますが、Recall機能がInternet Mailには無効である理由を考えてみます。