PEPMessage.cs
author Dean Looyengoed
Thu, 24 Mar 2016 21:54:53 +0100
changeset 721 be0c7d91b9f3
parent 703 131e11ffa292
child 722 f12a7eed140d
permissions -rw-r--r--
Implement ReceivedOn and SentOn date and time in PEPMessage.
Dean@384
     1
´╗┐using Microsoft.Win32;
Dean@384
     2
using pEpCOMServerAdapterLib;
Dean@384
     3
using System;
Dean@384
     4
using System.Collections.Generic;
Dean@384
     5
using System.IO;
Dean@384
     6
using System.Runtime.InteropServices;
Dean@384
     7
using Outlook = Microsoft.Office.Interop.Outlook;
Dean@384
     8
Dean@384
     9
namespace pEp
Dean@384
    10
{
Dean@384
    11
    /// <summary>
Dean@389
    12
    /// Class for a completely in-memory message based on the pEp engine text_message.
Dean@384
    13
    /// </summary>
Dean@389
    14
    public class PEPMessage : Interfaces.ICopy<PEPMessage>
Dean@384
    15
    {
Dean@572
    16
        // pEp properties
Dean@586
    17
        public const string PR_OPT_FIELD     = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/";
Dean@572
    18
        public const string PR_X_ENC_STATUS  = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-EncStatus";
Dean@572
    19
        public const string PR_X_KEY_LIST    = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-KeyList";
Dean@572
    20
        public const string PR_X_PEP_VERSION = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-pEp-Version";
Dean@572
    21
Dean@586
    22
        public const string PR_X_ENC_STATUS_NAME  = "X-EncStatus";
Dean@586
    23
        public const string PR_X_KEY_LIST_NAME    = "X-KeyList";
Dean@586
    24
        public const string PR_X_PEP_VERSION_NAME = "X-pEp-Version";
Dean@721
    25
        
Dean@384
    26
        private List<PEPAttachment> _Attachments;
Dean@384
    27
        private List<PEPIdentity>   _BCC;
Dean@384
    28
        private List<PEPIdentity>   _CC;
Dean@384
    29
        private _pEp_msg_direction  _Direction;
Dean@384
    30
        private PEPIdentity         _From;
Dean@384
    31
        private string              _ID;
Dean@384
    32
        private List<string>        _Keywords;
Dean@384
    33
        private string              _LongMsg;
Dean@697
    34
        private string              _LongMsgFormattedHTML;
Dean@697
    35
        private string              _LongMsgFormattedRTF;
Dean@572
    36
        private List<opt_field>     _OptionalProperties;
Dean@721
    37
        private DateTime?           _ReceivedOn;
Dean@721
    38
        private DateTime?           _SentOn;
Dean@384
    39
        private string              _ShortMsg;
Dean@384
    40
        private List<PEPIdentity>   _To;
Dean@384
    41
Dean@384
    42
        /**************************************************************
Dean@384
    43
         * 
Dean@384
    44
         * Constructors
Dean@384
    45
         * 
Dean@384
    46
         *************************************************************/
Dean@384
    47
Dean@384
    48
        /// <summary>
Dean@384
    49
        /// Default constructor.
Dean@384
    50
        /// </summary>
Dean@384
    51
        public PEPMessage()
Dean@384
    52
        {
Dean@384
    53
            this._Attachments = new List<PEPAttachment>();
Dean@384
    54
            this._BCC = new List<PEPIdentity>();
Dean@384
    55
            this._CC = new List<PEPIdentity>();
Dean@384
    56
            this._Direction = _pEp_msg_direction.pEp_dir_incoming;
Dean@384
    57
            this._From = null;
Dean@384
    58
            this._ID = null;
Dean@384
    59
            this._Keywords = new List<string>();
Dean@384
    60
            this._LongMsg = null;
Dean@697
    61
            this._LongMsgFormattedHTML = null;
Dean@697
    62
            this._LongMsgFormattedRTF = null;
Dean@572
    63
            this._OptionalProperties = new List<opt_field>();
Dean@721
    64
            this._ReceivedOn = null;
Dean@721
    65
            this._SentOn = null;
Dean@384
    66
            this._ShortMsg = null;
Dean@384
    67
            this._To = new List<PEPIdentity>();
Dean@384
    68
        }
Dean@384
    69
Dean@384
    70
        /// <summary>
Dean@384
    71
        /// Constructs a new message from the given pEp engine text_message.
Dean@384
    72
        /// </summary>
Dean@384
    73
        /// <param name="msg">The text_message to construct from.</param>
Dean@384
    74
        public PEPMessage(text_message msg)
Dean@384
    75
        {
Dean@384
    76
            // Attachments
Dean@384
    77
            this._Attachments = new List<PEPAttachment>();
Dean@384
    78
            if (msg.attachments != null)
Dean@384
    79
            {
Dean@384
    80
                for (int i = 0; i < msg.attachments.Length; i++)
Dean@384
    81
                {
Dean@384
    82
                    this._Attachments.Add(new PEPAttachment((blob)msg.attachments.GetValue(i)));
Dean@384
    83
                }
Dean@384
    84
            }
Dean@384
    85
Dean@384
    86
            // BCC
Dean@384
    87
            this._BCC = new List<PEPIdentity>();
Dean@384
    88
            if (msg.bcc != null)
Dean@384
    89
            {
Dean@384
    90
                for (int i = 0; i < msg.bcc.Length; i++)
Dean@384
    91
                {
Dean@384
    92
                    this._BCC.Add(new PEPIdentity((pEp_identity_s)msg.bcc.GetValue(i)));
Dean@384
    93
                }
Dean@384
    94
            }
Dean@384
    95
Dean@384
    96
            // CC
Dean@384
    97
            this._CC = new List<PEPIdentity>();
Dean@384
    98
            if (msg.cc != null)
Dean@384
    99
            {
Dean@384
   100
                for (int i = 0; i < msg.cc.Length; i++)
Dean@384
   101
                {
Dean@384
   102
                    this._CC.Add(new PEPIdentity((pEp_identity_s)msg.cc.GetValue(i)));
Dean@384
   103
                }
Dean@384
   104
            }
Dean@384
   105
Dean@384
   106
            this._Direction = msg.dir;
Dean@384
   107
            this._From = new PEPIdentity(msg.from);
Dean@384
   108
            this._ID = msg.id;
Dean@384
   109
Dean@384
   110
            // Keywords
Dean@384
   111
            this._Keywords = new List<string>();
Dean@384
   112
            if (msg.keywords != null)
Dean@384
   113
            {
Dean@384
   114
                for (int i = 0; i < msg.keywords.Length; i++)
Dean@384
   115
                {
Dean@384
   116
                    this._Keywords.Add((string)msg.keywords.GetValue(i));
Dean@384
   117
                }
Dean@384
   118
            }
Dean@384
   119
Dean@384
   120
            this._LongMsg = msg.longmsg;
Dean@697
   121
            this._LongMsgFormattedHTML = msg.longmsg_formatted;
Dean@697
   122
            this._LongMsgFormattedRTF = null;
Dean@384
   123
Dean@572
   124
            // Optional properties
Dean@572
   125
            this._OptionalProperties = new List<opt_field>();
Dean@384
   126
            if (msg.opt_fields != null)
Dean@384
   127
            {
Dean@384
   128
                for (int i = 0; i < msg.opt_fields.Length; i++)
Dean@384
   129
                {
Dean@572
   130
                    this._OptionalProperties.Add((opt_field)msg.opt_fields.GetValue(i));
Dean@384
   131
                }
Dean@384
   132
            }
Dean@384
   133
Dean@721
   134
            // ReceivedOn
Dean@721
   135
            if (msg.recv > 0)
Dean@721
   136
            {
Dean@721
   137
                this._ReceivedOn = new DateTime(1970, 1, 1).AddSeconds(msg.recv);
Dean@721
   138
            }
Dean@721
   139
            else
Dean@721
   140
            {
Dean@721
   141
                this._ReceivedOn = null;
Dean@721
   142
            }
Dean@721
   143
Dean@721
   144
            // SentOn
Dean@721
   145
            if (msg.sent > 0)
Dean@721
   146
            {
Dean@721
   147
                this._SentOn = new DateTime(1970, 1, 1).AddSeconds(msg.sent);
Dean@721
   148
            }
Dean@721
   149
            else
Dean@721
   150
            {
Dean@721
   151
                this._SentOn = null;
Dean@721
   152
            }
Dean@721
   153
Dean@384
   154
            this._ShortMsg = msg.shortmsg;
Dean@384
   155
Dean@384
   156
            // To
Dean@384
   157
            this._To = new List<PEPIdentity>();
Dean@384
   158
            if (msg.to != null)
Dean@384
   159
            {
Dean@384
   160
                for (int i = 0; i < msg.to.Length; i++)
Dean@384
   161
                {
Dean@384
   162
                    this._To.Add(new PEPIdentity((pEp_identity_s)msg.to.GetValue(i)));
Dean@384
   163
                }
Dean@384
   164
            }
Dean@384
   165
        }
Dean@384
   166
Dean@384
   167
        /// <summary>
Dean@384
   168
        /// Contructs a new message from the given outlook mail item.
Dean@384
   169
        /// </summary>
Dean@384
   170
        /// <param name="omi">The outlook mail item to create the message from.</param>
Dean@586
   171
        /// <param name="createWithoutContent">Whether to include content such as text body, attachments 
Dean@586
   172
        /// and optional properties.</param>
Dean@384
   173
        public PEPMessage(Outlook.MailItem omi,
Dean@384
   174
                          bool createWithoutContent = false)
Dean@384
   175
        {
Dean@698
   176
            byte[] rtfBody;
Dean@384
   177
            string delim;
Dean@384
   178
            string bodyLong = null;
Dean@697
   179
            string bodyLongFormattedHTML = null;
Dean@697
   180
            string bodyLongFormattedRTF = null;
Dean@586
   181
            object propertyValue;
Dean@586
   182
            opt_field newProp;
Dean@721
   183
            DateTime? receivedOn = null;
Dean@721
   184
            DateTime? sentOn = null;
Dean@384
   185
            List<string> keywordList = new List<string>();
Dean@384
   186
            List<PEPIdentity> toList = new List<PEPIdentity>();
Dean@384
   187
            List<PEPIdentity> ccList = new List<PEPIdentity>();
Dean@384
   188
            List<PEPIdentity> bccList = new List<PEPIdentity>();
Dean@384
   189
            List<PEPAttachment> attachmentList = new List<PEPAttachment>();
Dean@586
   190
            List<opt_field> optionalPropertyList = new List<opt_field>();
Dean@384
   191
            Outlook.Account acct = null;
Dean@551
   192
            Outlook.Attachment currAttachment = null;
Dean@551
   193
            Outlook.Attachments attachments = null;
Dean@551
   194
            Outlook.Recipient currRecipient = null;
Dean@551
   195
            Outlook.Recipients recipients = null;
Dean@499
   196
Dean@384
   197
            // Calculate recipients
Dean@551
   198
            recipients = omi.Recipients;
Dean@551
   199
            for (int i = 1; i <= recipients.Count; i++)
Dean@384
   200
            {
Dean@551
   201
                currRecipient = recipients[i];
Dean@551
   202
Dean@551
   203
                switch ((Outlook.OlMailRecipientType)currRecipient.Type)
Dean@384
   204
                {
Dean@384
   205
                    case Outlook.OlMailRecipientType.olTo:
Dean@551
   206
                        toList.Add(PEPIdentity.ToIdentity(currRecipient));
Dean@384
   207
                        break;
Dean@384
   208
                    case Outlook.OlMailRecipientType.olCC:
Dean@551
   209
                        ccList.Add(PEPIdentity.ToIdentity(currRecipient));
Dean@384
   210
                        break;
Dean@384
   211
                    case Outlook.OlMailRecipientType.olBCC:
Dean@551
   212
                        bccList.Add(PEPIdentity.ToIdentity(currRecipient));
Dean@384
   213
                        break;
Dean@384
   214
                }
Dean@551
   215
Dean@551
   216
                Marshal.ReleaseComObject(currRecipient);
Dean@551
   217
                currRecipient = null;
Dean@384
   218
            }
Dean@384
   219
Dean@721
   220
            /* Date & Times
Dean@721
   221
             * 
Dean@721
   222
             * Note: The mail item date can be invalid:
Dean@703
   223
             * For incoming this commonly occurs when creating a mirror -- it's created without a received time.
Dean@703
   224
             * For outgoing this commonly occurs for unsent mail.
Dean@703
   225
             * In these cases, the invalid date and time will be returned as 1/1/4501 at 12:00AM
Dean@703
   226
             * This situation is filtered here and the date is set as null.
Dean@703
   227
             */
Dean@721
   228
            receivedOn = omi.ReceivedTime;
Dean@721
   229
            if ((receivedOn != null) &&
Dean@721
   230
                (((DateTime)receivedOn).Year > 4000)) // ~2000 years from now, no issue
Dean@703
   231
            {
Dean@721
   232
                receivedOn = null;
Dean@721
   233
            }
Dean@721
   234
Dean@721
   235
            sentOn = omi.SentOn;
Dean@721
   236
            if ((sentOn != null) &&
Dean@721
   237
                (((DateTime)sentOn).Year > 4000)) // ~2000 years from now, no issue
Dean@721
   238
            {
Dean@721
   239
                sentOn = null;
Dean@691
   240
            }
Dean@691
   241
Dean@384
   242
            // Calculate text body and attachments
Dean@384
   243
            if (createWithoutContent == false)
Dean@384
   244
            {
Dean@384
   245
                // Body
Dean@384
   246
                if (omi.Body != null)
Dean@384
   247
                {
Dean@384
   248
                    bodyLong = omi.Body.Replace("\r\n", "\n");
Dean@384
   249
Dean@697
   250
                    // Save as RTF
Dean@698
   251
                    rtfBody = omi.RTFBody;
Dean@698
   252
                    bodyLongFormattedRTF = System.Text.Encoding.ASCII.GetString(rtfBody, 0, rtfBody.Length);
Dean@697
   253
Dean@384
   254
                    // Force rich text into HTML
Dean@384
   255
                    if (omi.BodyFormat == Outlook.OlBodyFormat.olFormatRichText)
Dean@384
   256
                    {
Dean@384
   257
                        omi.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
Dean@384
   258
                    }
Dean@384
   259
Dean@384
   260
                    if (omi.BodyFormat == Outlook.OlBodyFormat.olFormatHTML)
Dean@384
   261
                    {
Dean@697
   262
                        bodyLongFormattedHTML = omi.HTMLBody;
Dean@384
   263
                    }
Dean@384
   264
                }
Dean@384
   265
Dean@384
   266
                // Attachments
Dean@551
   267
                attachments = omi.Attachments;
Dean@551
   268
                for (int i = 1; i <= attachments.Count; i++)
Dean@384
   269
                {
Dean@551
   270
                    currAttachment = attachments[i];
Dean@551
   271
Dean@384
   272
                    try
Dean@384
   273
                    {
Dean@551
   274
                        attachmentList.Add(new PEPAttachment(currAttachment));
Dean@384
   275
                    }
Dean@384
   276
                    catch { }
Dean@551
   277
Dean@551
   278
                    Marshal.ReleaseComObject(currAttachment);
Dean@551
   279
                    currAttachment = null;
Dean@384
   280
                }
Dean@384
   281
Dean@384
   282
                // Keywords
Dean@384
   283
                if (omi.Categories != null)
Dean@384
   284
                {
Dean@384
   285
                    using (RegistryKey key1 = Registry.CurrentUser.OpenSubKey("Control Panel\\International"))
Dean@384
   286
                    {
Dean@384
   287
                        delim = key1.GetValue("sList").ToString();
Dean@384
   288
                        keywordList = new List<string>(omi.Categories.Split(delim.ToCharArray()));
Dean@384
   289
                    }
Dean@384
   290
                }
Dean@572
   291
Dean@586
   292
                // Optional properties
Dean@586
   293
                propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_ENC_STATUS);
Dean@586
   294
                if (propertyValue != null)
Dean@586
   295
                {
Dean@586
   296
                    newProp = new opt_field();
Dean@586
   297
                    newProp.name = PEPMessage.PR_X_ENC_STATUS_NAME;
Dean@586
   298
                    newProp.value = propertyValue.ToString();
Dean@586
   299
Dean@586
   300
                    optionalPropertyList.Add(newProp);
Dean@586
   301
                }
Dean@586
   302
Dean@586
   303
                propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_KEY_LIST);
Dean@586
   304
                if (propertyValue != null)
Dean@586
   305
                {
Dean@586
   306
                    newProp = new opt_field();
Dean@586
   307
                    newProp.name = PEPMessage.PR_X_KEY_LIST_NAME;
Dean@586
   308
                    newProp.value = propertyValue.ToString();
Dean@586
   309
Dean@586
   310
                    optionalPropertyList.Add(newProp);
Dean@586
   311
                }
Dean@586
   312
Dean@586
   313
                propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_PEP_VERSION);
Dean@586
   314
                if (propertyValue != null)
Dean@586
   315
                {
Dean@586
   316
                    newProp = new opt_field();
Dean@586
   317
                    newProp.name = PEPMessage.PR_X_PEP_VERSION_NAME;
Dean@586
   318
                    newProp.value = propertyValue.ToString();
Dean@586
   319
Dean@586
   320
                    optionalPropertyList.Add(newProp);
Dean@586
   321
                }
Dean@384
   322
            }
Dean@384
   323
Dean@384
   324
            // Set properties
Dean@384
   325
            this._Attachments = attachmentList;
Dean@384
   326
            this._BCC = bccList;
Dean@384
   327
            this._CC = ccList;
Dean@384
   328
            this._Direction = CryptableMailItem.GetIsIncoming(omi) ? _pEp_msg_direction.pEp_dir_incoming : _pEp_msg_direction.pEp_dir_outgoing;
Dean@643
   329
            this._From = PEPIdentity.GetFromIdentity(omi);
Dean@384
   330
            this._ID = CryptableMailItem.GetMessageID(omi);
Dean@384
   331
            this._Keywords = keywordList;
Dean@384
   332
            this._LongMsg = bodyLong;
Dean@697
   333
            this._LongMsgFormattedHTML = bodyLongFormattedHTML;
Dean@697
   334
            this._LongMsgFormattedRTF = bodyLongFormattedRTF;
Dean@586
   335
            this._OptionalProperties = optionalPropertyList;
Dean@721
   336
            this._ReceivedOn = receivedOn;
Dean@721
   337
            this._SentOn = sentOn;
Dean@384
   338
            this._ShortMsg = omi.Subject;
Dean@384
   339
            this._To = toList;
Dean@384
   340
Dean@384
   341
            // Free resources
Dean@384
   342
            if (acct != null)
Dean@384
   343
            {
Dean@384
   344
                Marshal.ReleaseComObject(acct);
Dean@384
   345
                acct = null;
Dean@384
   346
            }
Dean@384
   347
Dean@551
   348
            if (currAttachment != null)
Dean@551
   349
            {
Dean@551
   350
                Marshal.ReleaseComObject(currAttachment);
Dean@551
   351
                currAttachment = null;
Dean@551
   352
            }
Dean@551
   353
Dean@551
   354
            if (attachments != null)
Dean@551
   355
            {
Dean@551
   356
                Marshal.ReleaseComObject(attachments);
Dean@551
   357
                attachments = null;
Dean@551
   358
            }
Dean@551
   359
Dean@551
   360
            if (currRecipient != null)
Dean@551
   361
            {
Dean@551
   362
                Marshal.ReleaseComObject(currRecipient);
Dean@551
   363
                currRecipient = null;
Dean@551
   364
            }
Dean@551
   365
Dean@551
   366
            if (recipients != null)
Dean@551
   367
            {
Dean@551
   368
                Marshal.ReleaseComObject(recipients);
Dean@551
   369
                recipients = null;
Dean@551
   370
            }
Dean@551
   371
Dean@384
   372
            return;
Dean@384
   373
        }
Dean@384
   374
Dean@384
   375
        /**************************************************************
Dean@384
   376
         * 
Dean@384
   377
         * Property Accessors
Dean@384
   378
         * 
Dean@384
   379
         *************************************************************/
Dean@384
   380
Dean@384
   381
        /// <summary>
Dean@384
   382
        /// Gets the list of attachements for this message.
Dean@384
   383
        /// </summary>
Dean@384
   384
        public List<PEPAttachment> Attachments
Dean@384
   385
        {
Dean@384
   386
            get { return (this._Attachments); }
Dean@384
   387
        }
Dean@384
   388
Dean@384
   389
        /// <summary>
Dean@387
   390
        /// Gets the list of identities to be blind carbon copied on the message.
Dean@384
   391
        /// </summary>
Dean@384
   392
        public List<PEPIdentity> BCC
Dean@384
   393
        {
Dean@384
   394
            get { return (this._BCC); }
Dean@384
   395
        }
Dean@384
   396
Dean@384
   397
        /// <summary>
Dean@384
   398
        /// Gets the list of identities to be carbon copied on the message.
Dean@384
   399
        /// </summary>
Dean@384
   400
        public List<PEPIdentity> CC
Dean@384
   401
        {
Dean@384
   402
            get { return (this._CC); }
Dean@384
   403
        }
Dean@384
   404
Dean@384
   405
        /// <summary>
Dean@721
   406
        /// Gets the date and time when the message was either sent or received.
Dean@721
   407
        /// This corresponds with the SentOn and ReceivedOn properties.
Dean@691
   408
        /// </summary>
Dean@691
   409
        public DateTime? DateTimeSentOrReceived
Dean@691
   410
        {
Dean@721
   411
            get
Dean@721
   412
            {
Dean@721
   413
                if (this._Direction == _pEp_msg_direction.pEp_dir_incoming)
Dean@721
   414
                {
Dean@721
   415
                    return (this._ReceivedOn);
Dean@721
   416
                }
Dean@721
   417
                else
Dean@721
   418
                {
Dean@721
   419
                    return (this._SentOn);
Dean@721
   420
                }
Dean@721
   421
            }
Dean@691
   422
        }
Dean@691
   423
Dean@691
   424
        /// <summary>
Dean@384
   425
        /// Gets or sets the direction (incoming or outgoing) of the message.
Dean@384
   426
        /// </summary>
Dean@384
   427
        public _pEp_msg_direction Direction
Dean@384
   428
        {
Dean@384
   429
            get { return (this._Direction); }
Dean@384
   430
            set { this._Direction = value; }
Dean@384
   431
        }
Dean@384
   432
Dean@384
   433
        /// <summary>
Dean@384
   434
        /// Gets or sets the from identity of the message.
Dean@384
   435
        /// Warning: this value can be null.
Dean@384
   436
        /// </summary>
Dean@384
   437
        public PEPIdentity From
Dean@384
   438
        {
Dean@384
   439
            get { return (this._From); }
Dean@384
   440
            set { this._From = value; }
Dean@384
   441
        }
Dean@384
   442
Dean@384
   443
        /// <summary>
Dean@384
   444
        /// Gets or sets the ID of the message.
Dean@384
   445
        /// Warning: this value can be null.
Dean@384
   446
        /// </summary>
Dean@384
   447
        public string ID
Dean@384
   448
        {
Dean@384
   449
            get { return (this._ID); }
Dean@384
   450
            set { this._ID = value; }
Dean@384
   451
        }
Dean@384
   452
Dean@384
   453
        /// <summary>
Dean@384
   454
        /// Gets the list of keywords associated with the message.
Dean@384
   455
        /// </summary>
Dean@384
   456
        public List<string> Keywords
Dean@384
   457
        {
Dean@384
   458
            get { return (this._Keywords); }
Dean@384
   459
        }
Dean@384
   460
Dean@384
   461
        /// <summary>
Dean@384
   462
        /// Gets or sets the long-form (body) of the message.
Dean@384
   463
        /// This should be plain text.
Dean@384
   464
        /// Warning: this value can be null.
Dean@384
   465
        /// </summary>
Dean@384
   466
        public string LongMsg
Dean@384
   467
        {
Dean@384
   468
            get { return (this._LongMsg); }
Dean@384
   469
            set { this._LongMsg = value; }
Dean@384
   470
        }
Dean@384
   471
Dean@384
   472
        /// <summary>
Dean@697
   473
        /// Gets or sets the HTML formatted long-form (body) of the message.
Dean@384
   474
        /// Warning: this value can be null.
Dean@384
   475
        /// </summary>
Dean@697
   476
        public string LongMsgFormattedHTML
Dean@384
   477
        {
Dean@697
   478
            get { return (this._LongMsgFormattedHTML); }
Dean@697
   479
            set { this._LongMsgFormattedHTML = value; }
Dean@697
   480
        }
Dean@697
   481
Dean@697
   482
        /// <summary>
Dean@697
   483
        /// Gets or sets the RTF formatted long-form (body) of the message.
Dean@697
   484
        /// Warning: this value can be null.
Dean@697
   485
        /// </summary>
Dean@697
   486
        public string LongMsgFormattedRTF
Dean@697
   487
        {
Dean@697
   488
            get { return (this._LongMsgFormattedRTF); }
Dean@697
   489
            set { this._LongMsgFormattedRTF = value; }
Dean@384
   490
        }
Dean@384
   491
Dean@384
   492
        /// <summary>
Dean@572
   493
        /// Gets the list of optional properties associated with the message.
Dean@384
   494
        /// </summary>
Dean@572
   495
        public List<opt_field> OptionalProperties
Dean@384
   496
        {
Dean@572
   497
            get { return (this._OptionalProperties); }
Dean@384
   498
        }
Dean@384
   499
Dean@384
   500
        /// <summary>
Dean@721
   501
        /// Gets or sets the date and time when the message was received.
Dean@721
   502
        /// </summary>
Dean@721
   503
        public DateTime? ReceivedOn
Dean@721
   504
        {
Dean@721
   505
            get { return (this._ReceivedOn); }
Dean@721
   506
            set { this._ReceivedOn = value; }
Dean@721
   507
        }
Dean@721
   508
Dean@721
   509
        /// <summary>
Dean@721
   510
        /// Gets or sets the date and time when the message was sent.
Dean@721
   511
        /// </summary>
Dean@721
   512
        public DateTime? SentOn
Dean@721
   513
        {
Dean@721
   514
            get { return (this._SentOn); }
Dean@721
   515
            set { this._SentOn = value; }
Dean@721
   516
        }
Dean@721
   517
Dean@721
   518
        /// <summary>
Dean@384
   519
        /// Gets or sets the short-form (subject) of the message.
Dean@384
   520
        /// Warning: this value can be null.
Dean@384
   521
        /// </summary>
Dean@384
   522
        public string ShortMsg
Dean@384
   523
        {
Dean@384
   524
            get { return (this._ShortMsg); }
Dean@384
   525
            set { this._ShortMsg = value; }
Dean@384
   526
        }
Dean@384
   527
Dean@384
   528
        /// <summary>
Dean@384
   529
        /// Gets the list of identities to receive the message.
Dean@384
   530
        /// </summary>
Dean@384
   531
        public List<PEPIdentity> To
Dean@384
   532
        {
Dean@384
   533
            get { return (this._To); }
Dean@384
   534
        }
Dean@384
   535
Dean@625
   536
        /// <summary>
Dean@625
   537
        /// Gets the total number of all recipients in the message (BCC, CC &amp; To).
Dean@625
   538
        /// </summary>
Dean@625
   539
        public int RecipientCount
Dean@625
   540
        {
Dean@625
   541
            get { return (this._BCC.Count + this._CC.Count + this._To.Count); }
Dean@625
   542
        }
Dean@625
   543
Dean@625
   544
        /// <summary>
Dean@625
   545
        /// Gets a list of all recipients in the message (BCC, CC &amp; To).
Dean@625
   546
        /// Each recipient in the returned list is a copy.
Dean@625
   547
        /// </summary>
Dean@625
   548
        public PEPIdentity[] Recipients
Dean@625
   549
        {
Dean@625
   550
            get
Dean@625
   551
            {
Dean@625
   552
                List<PEPIdentity> recipients = new List<PEPIdentity>();
Dean@625
   553
Dean@625
   554
                // BCC
Dean@625
   555
                for (int i = 0; i < this._BCC.Count; i++)
Dean@625
   556
                {
Dean@625
   557
                    recipients.Add(this._BCC[i].Copy());
Dean@625
   558
                }
Dean@625
   559
Dean@625
   560
                // CC
Dean@625
   561
                for (int i = 0; i < this._CC.Count; i++)
Dean@625
   562
                {
Dean@625
   563
                    recipients.Add(this._CC[i].Copy());
Dean@625
   564
                }
Dean@625
   565
Dean@625
   566
                // To
Dean@625
   567
                for (int i = 0; i < this._To.Count; i++)
Dean@625
   568
                {
Dean@625
   569
                    recipients.Add(this._To[i].Copy());
Dean@625
   570
                }
Dean@625
   571
Dean@625
   572
                return (recipients.ToArray());
Dean@625
   573
            }
Dean@625
   574
        }
Dean@625
   575
Dean@384
   576
        /**************************************************************
Dean@384
   577
         * 
Dean@384
   578
         * Methods
Dean@384
   579
         * 
Dean@384
   580
         *************************************************************/
Dean@384
   581
Dean@384
   582
        /// <summary>
Dean@384
   583
        /// Returns this pEp message as a new pEp engine text_message.
Dean@384
   584
        /// </summary>
Dean@384
   585
        /// <returns>A pEp engine identity.</returns>
Dean@384
   586
        public text_message ToCOMType()
Dean@384
   587
        {
Dean@384
   588
            List<blob> attachments = new List<blob>();
Dean@384
   589
            List<pEp_identity_s> bcc = new List<pEp_identity_s>();
Dean@384
   590
            List<pEp_identity_s> cc = new List<pEp_identity_s>();
Dean@384
   591
            List<pEp_identity_s> to = new List<pEp_identity_s>();
Dean@384
   592
            text_message result = new text_message();
Dean@384
   593
Dean@388
   594
            // Convert attachments
Dean@384
   595
            for (int i = 0; i < this._Attachments.Count; i++)
Dean@384
   596
            {
Dean@384
   597
                attachments.Add(this._Attachments[i].ToCOMType());
Dean@384
   598
            }
Dean@398
   599
Dean@388
   600
            // Convert BCC
Dean@384
   601
            for (int i = 0; i < this._BCC.Count; i++)
Dean@384
   602
            {
Dean@384
   603
                bcc.Add(this._BCC[i].ToCOMType());
Dean@384
   604
            }
Dean@398
   605
Dean@388
   606
            // Convert CC
Dean@384
   607
            for (int i = 0; i < this._CC.Count; i++)
Dean@384
   608
            {
Dean@384
   609
                cc.Add(this._CC[i].ToCOMType());
Dean@384
   610
            }
Dean@398
   611
Dean@388
   612
            // Convert To
Dean@388
   613
            for (int i = 0; i < this._To.Count; i++)
Dean@388
   614
            {
Dean@388
   615
                to.Add(this._To[i].ToCOMType());
Dean@388
   616
            }
Dean@388
   617
Dean@697
   618
            /* Set properties
Dean@697
   619
             * 
Dean@697
   620
             * Note: Skip DateTimeSentOrReceived and LongMsgFormattedRTF which
Dean@697
   621
             * are not supported in the pEp engine.
Dean@697
   622
             */
Dean@388
   623
            result.attachments = attachments.ToArray();
Dean@388
   624
            result.bcc = bcc.ToArray();
Dean@384
   625
            result.cc = cc.ToArray();
Dean@384
   626
            result.dir = this._Direction;
Dean@384
   627
            result.from = (this._From == null ? new pEp_identity_s() : this._From.ToCOMType());
Dean@384
   628
            result.id = this._ID;
Dean@384
   629
            result.keywords = this._Keywords.ToArray();
Dean@384
   630
            result.longmsg = this._LongMsg;
Dean@697
   631
            result.longmsg_formatted = this._LongMsgFormattedHTML;
Dean@572
   632
            result.opt_fields = this._OptionalProperties.ToArray();
Dean@384
   633
            result.shortmsg = this._ShortMsg;
Dean@384
   634
            result.to = to.ToArray();
Dean@384
   635
Dean@384
   636
            return (result);
Dean@384
   637
        }
Dean@384
   638
Dean@384
   639
        /// <summary>
Dean@389
   640
        /// Gets a deep copy of the object and all it's data.
Dean@389
   641
        /// </summary>
Dean@389
   642
        /// <returns>The deep copy of the object.</returns>
Dean@389
   643
        public PEPMessage Copy()
Dean@389
   644
        {
Dean@390
   645
            return (this.Copy(false));
Dean@390
   646
        }
Dean@390
   647
Dean@390
   648
        /// <summary>
Dean@390
   649
        /// Gets a copy of the PEPMessage with or without data.
Dean@390
   650
        /// </summary>
Dean@586
   651
        /// <param name="createWithoutContent">Whether to include content such as text body, attachments 
Dean@586
   652
        /// and optional properties.</param>
Dean@390
   653
        /// <returns>The copy of the PEPMessage.</returns>
Dean@390
   654
        public PEPMessage Copy(bool createWithoutContent = false)
Dean@390
   655
        {
Dean@389
   656
            PEPMessage copy = new PEPMessage();
Dean@389
   657
Dean@389
   658
            // Attachments
Dean@389
   659
            copy.Attachments.Clear();
Dean@390
   660
            if (createWithoutContent == false)
Dean@389
   661
            {
Dean@390
   662
                for (int i = 0; i < this._Attachments.Count; i++)
Dean@390
   663
                {
Dean@390
   664
                    copy.Attachments.Add(this._Attachments[i].Copy());
Dean@390
   665
                }
Dean@389
   666
            }
Dean@389
   667
Dean@389
   668
            // BCC
Dean@389
   669
            copy.BCC.Clear();
Dean@389
   670
            for (int i = 0; i < this._BCC.Count; i++)
Dean@389
   671
            {
Dean@389
   672
                copy.BCC.Add(this._BCC[i].Copy());
Dean@389
   673
            }
Dean@389
   674
Dean@389
   675
            // CC
Dean@389
   676
            copy.CC.Clear();
Dean@389
   677
            for (int i = 0; i < this._CC.Count; i++)
Dean@389
   678
            {
Dean@389
   679
                copy.CC.Add(this._CC[i].Copy());
Dean@389
   680
            }
Dean@389
   681
Dean@389
   682
            copy.Direction = this._Direction;
Dean@389
   683
            copy.From = (this._From == null ? null : this._From.Copy());
Dean@389
   684
            copy.ID = this._ID;
Dean@389
   685
Dean@389
   686
            // Keywords
Dean@389
   687
            copy.Keywords.Clear();
Dean@389
   688
            for (int i = 0; i < this._Keywords.Count; i++)
Dean@389
   689
            {
Dean@389
   690
                copy.Keywords.Add(this._Keywords[i]);
Dean@389
   691
            }
Dean@398
   692
Dean@390
   693
            // Body
Dean@390
   694
            if (createWithoutContent == false)
Dean@390
   695
            {
Dean@390
   696
                copy.LongMsg = this._LongMsg;
Dean@697
   697
                copy.LongMsgFormattedHTML = this._LongMsgFormattedHTML;
Dean@697
   698
                copy.LongMsgFormattedRTF = this._LongMsgFormattedRTF;
Dean@390
   699
            }
Dean@390
   700
            else
Dean@390
   701
            {
Dean@390
   702
                copy.LongMsg = null;
Dean@697
   703
                copy.LongMsgFormattedHTML = null;
Dean@697
   704
                copy.LongMsgFormattedRTF = null;
Dean@390
   705
            }
Dean@389
   706
Dean@389
   707
            // OptionalFields
Dean@572
   708
            copy.OptionalProperties.Clear();
Dean@586
   709
            if (createWithoutContent == false)
Dean@389
   710
            {
Dean@586
   711
                for (int i = 0; i < this._OptionalProperties.Count; i++)
Dean@586
   712
                {
Dean@586
   713
                    copy.OptionalProperties.Add(this._OptionalProperties[i]);
Dean@586
   714
                }
Dean@389
   715
            }
Dean@604
   716
Dean@721
   717
            // ReceivedOn
Dean@721
   718
            if (this._ReceivedOn != null)
Dean@721
   719
            {
Dean@721
   720
                copy.ReceivedOn = new DateTime(((DateTime)this._ReceivedOn).Ticks);
Dean@721
   721
            }
Dean@721
   722
            else
Dean@721
   723
            {
Dean@721
   724
                copy.ReceivedOn = null;
Dean@721
   725
            }
Dean@721
   726
Dean@721
   727
            // SentOn
Dean@721
   728
            if (this._SentOn != null)
Dean@721
   729
            {
Dean@721
   730
                copy.SentOn = new DateTime(((DateTime)this._SentOn).Ticks);
Dean@721
   731
            }
Dean@721
   732
            else
Dean@721
   733
            {
Dean@721
   734
                copy.SentOn = null;
Dean@721
   735
            }
Dean@721
   736
Dean@389
   737
            copy.ShortMsg = this._ShortMsg;
Dean@389
   738
Dean@389
   739
            // To
Dean@389
   740
            copy.To.Clear();
Dean@389
   741
            for (int i = 0; i < this._To.Count; i++)
Dean@389
   742
            {
Dean@389
   743
                copy.To.Add(this._To[i].Copy());
Dean@389
   744
            }
Dean@389
   745
Dean@389
   746
            return (copy);
Dean@389
   747
        }
Dean@389
   748
Dean@389
   749
        /// <summary>
Dean@384
   750
        /// Applies this pEp message's data to the given Outlook item.
Dean@384
   751
        /// </summary>
Dean@384
   752
        /// <param name="omi">The Outlook mail item to apply this pEp message's data to.</param>
Dean@586
   753
        /// <param name="includeOptionalProperties">Whether to include optional properites such as 
Dean@586
   754
        /// color rating, pEp version etc...</param>
Dean@586
   755
        public void ApplyTo(Outlook.MailItem omi,
Dean@586
   756
                            bool includeOptionalProperties = false)
Dean@384
   757
        {
Dean@384
   758
            string tempDir;
Dean@384
   759
            string tempFile;
Dean@543
   760
            Outlook.Attachment newAttachment = null;
Dean@543
   761
            Outlook.Attachments attachments = null;
Dean@543
   762
            Outlook.Recipient newRecipient = null;
Dean@543
   763
            Outlook.Recipients recipients = null;
Dean@543
   764
            Outlook.Account currAccount = null;
Dean@543
   765
            Outlook.Account sendUsingAccount = null;
Dean@543
   766
            Outlook.Accounts accounts = null;
Dean@408
   767
Dean@543
   768
            try
Dean@408
   769
            {
Dean@543
   770
                // Remove all recipients
Dean@543
   771
                recipients = omi.Recipients;
Dean@543
   772
                while (recipients.Count > 0)
Dean@543
   773
                {
Dean@543
   774
                    recipients.Remove(1);
Dean@543
   775
                }
Dean@543
   776
Dean@543
   777
                // Set recipients
Dean@543
   778
                for (int i = 0; i < this._BCC.Count; i++)
Dean@543
   779
                {
Dean@543
   780
                    if (this._BCC[i].Address != null)
Dean@543
   781
                    {
Dean@543
   782
                        newRecipient = recipients.Add(this._BCC[i].Address);
Dean@543
   783
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olBCC;
Dean@543
   784
Dean@543
   785
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   786
                        newRecipient = null;
Dean@543
   787
                    }
Dean@543
   788
                }
Dean@543
   789
Dean@543
   790
                for (int i = 0; i < this._CC.Count; i++)
Dean@543
   791
                {
Dean@543
   792
                    if (this._CC[i].Address != null)
Dean@543
   793
                    {
Dean@543
   794
                        newRecipient = recipients.Add(this._CC[i].Address);
Dean@543
   795
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olCC;
Dean@543
   796
Dean@543
   797
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   798
                        newRecipient = null;
Dean@543
   799
                    }
Dean@543
   800
                }
Dean@543
   801
Dean@543
   802
                for (int i = 0; i < this._To.Count; i++)
Dean@543
   803
                {
Dean@543
   804
                    if (this._To[i].Address != null)
Dean@543
   805
                    {
Dean@543
   806
                        newRecipient = recipients.Add(this._To[i].Address);
Dean@543
   807
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olTo;
Dean@543
   808
Dean@543
   809
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   810
                        newRecipient = null;
Dean@543
   811
                    }
Dean@543
   812
                }
Dean@543
   813
Dean@543
   814
                recipients.ResolveAll();
Dean@543
   815
Dean@543
   816
                /* Set sender
Dean@543
   817
                 * Note that if fails, will be empty which eventually will use the default send account
Dean@543
   818
                 * If the send using account is already populated, this cannot be re-set.
Dean@543
   819
                 * So far this doesn't appear to be an issue as it occurs when applying unencrypted data to a mirror.
Dean@543
   820
                 * However, the mirror SendUsingAccount is already correct at this point and doesn't need to be set.
Dean@543
   821
                 */
Dean@543
   822
                sendUsingAccount = omi.SendUsingAccount;
Dean@543
   823
Dean@543
   824
                if ((this._From != null) &&
Dean@543
   825
                    (this._From.Address != null) &&
Dean@543
   826
                    (sendUsingAccount == null))
Dean@543
   827
                {
Dean@543
   828
                    accounts = Globals.ThisAddIn.Application.Session.Accounts;
Dean@543
   829
Dean@543
   830
                    // Note: Index starts at 1
Dean@543
   831
                    for (int i = 1; i <= accounts.Count; i++)
Dean@543
   832
                    {
Dean@543
   833
                        currAccount = accounts[i];
Dean@543
   834
Dean@543
   835
                        if ((currAccount.SmtpAddress != null) &&
Dean@543
   836
                            (currAccount.SmtpAddress.ToUpper() == this._From.Address.ToUpper()))
Dean@543
   837
                        {
Dean@543
   838
                            /* Try to set the SendUsingAccount
Dean@543
   839
                             * This will fail if the mail item is already marked as sent or the SendUsingAccount is not null, etc...
Dean@564
   840
                             * If it fails, Outlook will in the end just use the default account.
Dean@564
   841
                             * This property should ideally be set before a mail item is saved.
Dean@543
   842
                             */
Dean@543
   843
                            try
Dean@543
   844
                            {
Dean@564
   845
                                omi.SendUsingAccount = currAccount;
Dean@543
   846
                            }
Dean@543
   847
                            catch { }
Dean@543
   848
Dean@543
   849
                            Marshal.ReleaseComObject(currAccount);
Dean@543
   850
                            currAccount = null;
Dean@543
   851
Dean@543
   852
                            break;
Dean@543
   853
                        }
Dean@543
   854
Dean@543
   855
                        Marshal.ReleaseComObject(currAccount);
Dean@543
   856
                        currAccount = null;
Dean@543
   857
                    }
Dean@543
   858
                }
Dean@543
   859
Dean@543
   860
                // Set the subject
Dean@543
   861
                omi.Subject = this._ShortMsg;
Dean@543
   862
Dean@697
   863
                // Set the body (skip RTF format, only use HTML which is what the engine uses)
Dean@697
   864
                if (string.IsNullOrWhiteSpace(this._LongMsgFormattedHTML))
Dean@543
   865
                {
Dean@543
   866
                    omi.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
Dean@543
   867
                    omi.Body = this._LongMsg;
Dean@543
   868
                }
Dean@543
   869
                else
Dean@543
   870
                {
Dean@543
   871
                    omi.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
Dean@697
   872
                    omi.HTMLBody = this._LongMsgFormattedHTML;
Dean@543
   873
                }
Dean@543
   874
Dean@543
   875
                // Remove any previous attachments
Dean@543
   876
                attachments = omi.Attachments;
Dean@543
   877
                while (attachments.Count > 0)
Dean@543
   878
                {
Dean@543
   879
                    attachments.Remove(1);
Dean@543
   880
                }
Dean@543
   881
Dean@543
   882
                // Create temp directory for attachments
Dean@543
   883
                tempDir = Path.GetTempFileName() + ".dir";
Dean@543
   884
                Directory.CreateDirectory(tempDir);
Dean@543
   885
Dean@543
   886
                // Add new attachments
Dean@543
   887
                for (int i = 0; i < this._Attachments.Count; i++)
Dean@543
   888
                {
Dean@543
   889
                    // Write current attachment to disk
Dean@543
   890
                    tempFile = tempDir + "\\";
Dean@543
   891
                    if (string.IsNullOrWhiteSpace(this._Attachments[i].FileName))
Dean@543
   892
                    {
Dean@543
   893
                        tempFile += "attachment" + i.ToString();
Dean@543
   894
                    }
Dean@543
   895
                    else
Dean@543
   896
                    {
Dean@543
   897
                        tempFile += this._Attachments[i].FileName;
Dean@543
   898
                    }
Dean@543
   899
                    File.WriteAllBytes(tempFile, this._Attachments[i].Data);
Dean@543
   900
Dean@543
   901
                    // Create a new attachment from the file on disk
Dean@543
   902
                    newAttachment = attachments.Add(tempFile);
Dean@543
   903
Dean@543
   904
                    if (string.IsNullOrWhiteSpace(this._Attachments[i].MIMEType))
Dean@543
   905
                    {
Dean@543
   906
                        // Undefined
Dean@543
   907
                        PEPAttachment.SetMIMEType(newAttachment, "application/octet-stream");
Dean@543
   908
                    }
Dean@543
   909
                    else
Dean@543
   910
                    {
Dean@543
   911
                        PEPAttachment.SetMIMEType(newAttachment, this._Attachments[i].MIMEType);
Dean@543
   912
                    }
Dean@543
   913
Dean@543
   914
                    Marshal.ReleaseComObject(newAttachment);
Dean@543
   915
                    newAttachment = null;
Dean@543
   916
                }
Dean@543
   917
Dean@543
   918
                // Delete temp directory for attachments
Dean@543
   919
                Directory.Delete(tempDir, true);
Dean@543
   920
Dean@572
   921
                // Optional properties
Dean@586
   922
                if (includeOptionalProperties)
Dean@543
   923
                {
Dean@586
   924
                    for (int i = 0; i < this._OptionalProperties.Count; i++)
Dean@586
   925
                    {
Dean@586
   926
                        MAPIHelper.SetProperty(omi,
Dean@586
   927
                                               PEPMessage.PR_OPT_FIELD + this._OptionalProperties[i].name,
Dean@586
   928
                                               this._OptionalProperties[i].value);
Dean@586
   929
                    }
Dean@543
   930
                }
Dean@408
   931
            }
Dean@545
   932
            catch (Exception ex)
Dean@545
   933
            {
Dean@660
   934
                Global.StopAndSendCrashReport(ex);
Dean@545
   935
            }
Dean@543
   936
            finally
Dean@543
   937
            {
Dean@543
   938
                if (newAttachment != null)
Dean@543
   939
                {
Dean@543
   940
                    Marshal.ReleaseComObject(newAttachment);
Dean@543
   941
                    newAttachment = null;
Dean@543
   942
                }
Dean@408
   943
Dean@543
   944
                if (attachments != null)
Dean@466
   945
                {
Dean@543
   946
                    Marshal.ReleaseComObject(attachments);
Dean@543
   947
                    attachments = null;
Dean@543
   948
                }
Dean@408
   949
Dean@543
   950
                if (newRecipient != null)
Dean@543
   951
                {
Dean@466
   952
                    Marshal.ReleaseComObject(newRecipient);
Dean@543
   953
                    newRecipient = null;
Dean@543
   954
                }
Dean@543
   955
Dean@543
   956
                if (recipients != null)
Dean@543
   957
                {
Dean@543
   958
                    Marshal.ReleaseComObject(recipients);
Dean@543
   959
                    recipients = null;
Dean@543
   960
                }
Dean@543
   961
Dean@543
   962
                if (currAccount != null)
Dean@543
   963
                {
Dean@543
   964
                    Marshal.ReleaseComObject(currAccount);
Dean@543
   965
                    currAccount = null;
Dean@543
   966
                }
Dean@543
   967
Dean@543
   968
                if (sendUsingAccount != null)
Dean@543
   969
                {
Dean@543
   970
                    Marshal.ReleaseComObject(sendUsingAccount);
Dean@543
   971
                    sendUsingAccount = null;
Dean@543
   972
                }
Dean@543
   973
Dean@543
   974
                if (accounts != null)
Dean@543
   975
                {
Dean@543
   976
                    Marshal.ReleaseComObject(accounts);
Dean@543
   977
                    accounts = null;
Dean@543
   978
                }
Dean@408
   979
            }
Dean@408
   980
Dean@384
   981
            return;
Dean@384
   982
        }
Dean@384
   983
Dean@398
   984
        /// <summary>
Dean@398
   985
        /// Recursivley converts all "BCC", "CC", and "To" identities into a 'flat' list of any members.
Dean@398
   986
        /// This will remove groups (hierarchy) and convert a group into it's members.
Dean@398
   987
        /// </summary>
Dean@398
   988
        public void FlattenAllRecipientIdentities()
Dean@398
   989
        {
Dean@398
   990
            this._BCC = PEPIdentity.ToFlatList(this._BCC);
Dean@398
   991
            this._CC = PEPIdentity.ToFlatList(this._CC);
Dean@398
   992
            this._To = PEPIdentity.ToFlatList(this._To);
Dean@398
   993
Dean@398
   994
            return;
Dean@398
   995
        }
Dean@413
   996
Dean@384
   997
    }
Dean@384
   998
}