送信済Mailを編集して送信した再送Mailを回収(Recall)する -3- | Lotus Notes/Domino (R) をこよなく愛して。。。。

送信済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のManualTechnoteを参照すれば分かりますが、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には無効である理由を考えてみます。

 

<続く>