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