PEPMessage.cs
author Dean Looyengoed
Tue, 24 May 2016 22:56:47 +0200
changeset 920 c4863531b31f
parent 910 9bd60ca2c6ac
child 927 ce3aac0a61e8
permissions -rw-r--r--
Correct NormalizeContentIDs calculation and make more robust.
This fixes an issue with multiple embedded images.
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@910
    14
    internal 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@780
    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
        /**************************************************************
Dean@384
    71
         * 
Dean@384
    72
         * Property Accessors
Dean@384
    73
         * 
Dean@384
    74
         *************************************************************/
Dean@384
    75
Dean@910
    76
        #region Property Accessors
Dean@910
    77
Dean@384
    78
        /// <summary>
Dean@384
    79
        /// Gets the list of attachements for this message.
Dean@384
    80
        /// </summary>
Dean@384
    81
        public List<PEPAttachment> Attachments
Dean@384
    82
        {
Dean@384
    83
            get { return (this._Attachments); }
Dean@384
    84
        }
Dean@384
    85
Dean@384
    86
        /// <summary>
Dean@387
    87
        /// Gets the list of identities to be blind carbon copied on the message.
Dean@384
    88
        /// </summary>
Dean@384
    89
        public List<PEPIdentity> BCC
Dean@384
    90
        {
Dean@384
    91
            get { return (this._BCC); }
Dean@384
    92
        }
Dean@384
    93
Dean@384
    94
        /// <summary>
Dean@384
    95
        /// Gets the list of identities to be carbon copied on the message.
Dean@384
    96
        /// </summary>
Dean@384
    97
        public List<PEPIdentity> CC
Dean@384
    98
        {
Dean@384
    99
            get { return (this._CC); }
Dean@384
   100
        }
Dean@384
   101
Dean@384
   102
        /// <summary>
Dean@721
   103
        /// Gets the date and time when the message was either sent or received.
Dean@721
   104
        /// This corresponds with the SentOn and ReceivedOn properties.
Dean@691
   105
        /// </summary>
Dean@691
   106
        public DateTime? DateTimeSentOrReceived
Dean@691
   107
        {
Dean@721
   108
            get
Dean@721
   109
            {
Dean@721
   110
                if (this._Direction == _pEp_msg_direction.pEp_dir_incoming)
Dean@721
   111
                {
Dean@721
   112
                    return (this._ReceivedOn);
Dean@721
   113
                }
Dean@721
   114
                else
Dean@721
   115
                {
Dean@721
   116
                    return (this._SentOn);
Dean@721
   117
                }
Dean@721
   118
            }
Dean@691
   119
        }
Dean@691
   120
Dean@691
   121
        /// <summary>
Dean@384
   122
        /// Gets or sets the direction (incoming or outgoing) of the message.
Dean@384
   123
        /// </summary>
Dean@384
   124
        public _pEp_msg_direction Direction
Dean@384
   125
        {
Dean@384
   126
            get { return (this._Direction); }
Dean@384
   127
            set { this._Direction = value; }
Dean@384
   128
        }
Dean@384
   129
Dean@384
   130
        /// <summary>
Dean@384
   131
        /// Gets or sets the from identity of the message.
Dean@384
   132
        /// Warning: this value can be null.
Dean@384
   133
        /// </summary>
Dean@384
   134
        public PEPIdentity From
Dean@384
   135
        {
Dean@384
   136
            get { return (this._From); }
Dean@384
   137
            set { this._From = value; }
Dean@384
   138
        }
Dean@384
   139
Dean@384
   140
        /// <summary>
Dean@384
   141
        /// Gets or sets the ID of the message.
Dean@384
   142
        /// Warning: this value can be null.
Dean@384
   143
        /// </summary>
Dean@384
   144
        public string ID
Dean@384
   145
        {
Dean@384
   146
            get { return (this._ID); }
Dean@384
   147
            set { this._ID = value; }
Dean@384
   148
        }
Dean@384
   149
Dean@384
   150
        /// <summary>
Dean@384
   151
        /// Gets the list of keywords associated with the message.
Dean@384
   152
        /// </summary>
Dean@384
   153
        public List<string> Keywords
Dean@384
   154
        {
Dean@384
   155
            get { return (this._Keywords); }
Dean@384
   156
        }
Dean@384
   157
Dean@384
   158
        /// <summary>
Dean@384
   159
        /// Gets or sets the long-form (body) of the message.
Dean@384
   160
        /// This should be plain text.
Dean@384
   161
        /// Warning: this value can be null.
Dean@384
   162
        /// </summary>
Dean@384
   163
        public string LongMsg
Dean@384
   164
        {
Dean@384
   165
            get { return (this._LongMsg); }
Dean@384
   166
            set { this._LongMsg = value; }
Dean@384
   167
        }
Dean@384
   168
Dean@384
   169
        /// <summary>
Dean@697
   170
        /// Gets or sets the HTML formatted long-form (body) of the message.
Dean@384
   171
        /// Warning: this value can be null.
Dean@384
   172
        /// </summary>
Dean@697
   173
        public string LongMsgFormattedHTML
Dean@384
   174
        {
Dean@697
   175
            get { return (this._LongMsgFormattedHTML); }
Dean@697
   176
            set { this._LongMsgFormattedHTML = value; }
Dean@697
   177
        }
Dean@697
   178
Dean@697
   179
        /// <summary>
Dean@697
   180
        /// Gets or sets the RTF formatted long-form (body) of the message.
Dean@697
   181
        /// Warning: this value can be null.
Dean@697
   182
        /// </summary>
Dean@697
   183
        public string LongMsgFormattedRTF
Dean@697
   184
        {
Dean@697
   185
            get { return (this._LongMsgFormattedRTF); }
Dean@697
   186
            set { this._LongMsgFormattedRTF = value; }
Dean@384
   187
        }
Dean@384
   188
Dean@384
   189
        /// <summary>
Dean@572
   190
        /// Gets the list of optional properties associated with the message.
Dean@384
   191
        /// </summary>
Dean@572
   192
        public List<opt_field> OptionalProperties
Dean@384
   193
        {
Dean@572
   194
            get { return (this._OptionalProperties); }
Dean@384
   195
        }
Dean@384
   196
Dean@384
   197
        /// <summary>
Dean@721
   198
        /// Gets or sets the date and time when the message was received.
Dean@721
   199
        /// </summary>
Dean@721
   200
        public DateTime? ReceivedOn
Dean@721
   201
        {
Dean@721
   202
            get { return (this._ReceivedOn); }
Dean@721
   203
            set { this._ReceivedOn = value; }
Dean@721
   204
        }
Dean@721
   205
Dean@721
   206
        /// <summary>
Dean@721
   207
        /// Gets or sets the date and time when the message was sent.
Dean@721
   208
        /// </summary>
Dean@721
   209
        public DateTime? SentOn
Dean@721
   210
        {
Dean@721
   211
            get { return (this._SentOn); }
Dean@721
   212
            set { this._SentOn = value; }
Dean@721
   213
        }
Dean@721
   214
Dean@721
   215
        /// <summary>
Dean@384
   216
        /// Gets or sets the short-form (subject) of the message.
Dean@384
   217
        /// Warning: this value can be null.
Dean@384
   218
        /// </summary>
Dean@384
   219
        public string ShortMsg
Dean@384
   220
        {
Dean@384
   221
            get { return (this._ShortMsg); }
Dean@384
   222
            set { this._ShortMsg = value; }
Dean@384
   223
        }
Dean@384
   224
Dean@384
   225
        /// <summary>
Dean@384
   226
        /// Gets the list of identities to receive the message.
Dean@384
   227
        /// </summary>
Dean@384
   228
        public List<PEPIdentity> To
Dean@384
   229
        {
Dean@384
   230
            get { return (this._To); }
Dean@384
   231
        }
Dean@384
   232
Dean@625
   233
        /// <summary>
Dean@625
   234
        /// Gets the total number of all recipients in the message (BCC, CC &amp; To).
Dean@625
   235
        /// </summary>
Dean@625
   236
        public int RecipientCount
Dean@625
   237
        {
Dean@625
   238
            get { return (this._BCC.Count + this._CC.Count + this._To.Count); }
Dean@625
   239
        }
Dean@625
   240
Dean@625
   241
        /// <summary>
Dean@625
   242
        /// Gets a list of all recipients in the message (BCC, CC &amp; To).
Dean@625
   243
        /// Each recipient in the returned list is a copy.
Dean@625
   244
        /// </summary>
Dean@625
   245
        public PEPIdentity[] Recipients
Dean@625
   246
        {
Dean@625
   247
            get
Dean@625
   248
            {
Dean@625
   249
                List<PEPIdentity> recipients = new List<PEPIdentity>();
Dean@625
   250
Dean@625
   251
                // BCC
Dean@625
   252
                for (int i = 0; i < this._BCC.Count; i++)
Dean@625
   253
                {
Dean@625
   254
                    recipients.Add(this._BCC[i].Copy());
Dean@625
   255
                }
Dean@625
   256
Dean@625
   257
                // CC
Dean@625
   258
                for (int i = 0; i < this._CC.Count; i++)
Dean@625
   259
                {
Dean@625
   260
                    recipients.Add(this._CC[i].Copy());
Dean@625
   261
                }
Dean@625
   262
Dean@625
   263
                // To
Dean@625
   264
                for (int i = 0; i < this._To.Count; i++)
Dean@625
   265
                {
Dean@625
   266
                    recipients.Add(this._To[i].Copy());
Dean@625
   267
                }
Dean@625
   268
Dean@625
   269
                return (recipients.ToArray());
Dean@625
   270
            }
Dean@625
   271
        }
Dean@625
   272
Dean@910
   273
        #endregion
Dean@910
   274
Dean@384
   275
        /**************************************************************
Dean@384
   276
         * 
Dean@384
   277
         * Methods
Dean@384
   278
         * 
Dean@384
   279
         *************************************************************/
Dean@384
   280
Dean@384
   281
        /// <summary>
Dean@910
   282
        /// Constructs a new message from the given pEp engine text_message.
Dean@910
   283
        /// The output will never be null.
Dean@910
   284
        /// </summary>
Dean@910
   285
        /// <param name="msg">The text_message to construct from.</param>
Dean@910
   286
        /// <param name="createdMessage">The output newly created message (will never be null).</param>
Dean@910
   287
        /// <returns>The status of the method.</returns>
Dean@910
   288
        public static Globals.ReturnStatus Create(text_message msg,
Dean@910
   289
                                                  out PEPMessage createdMessage)
Dean@910
   290
        {
Dean@910
   291
            Globals.ReturnStatus status = Globals.ReturnStatus.Success;
Dean@910
   292
            PEPMessage newMessage = new PEPMessage();
Dean@910
   293
Dean@910
   294
            try
Dean@910
   295
            {
Dean@910
   296
                // Attachments
Dean@910
   297
                newMessage.Attachments.Clear();
Dean@910
   298
                if (msg.attachments != null)
Dean@910
   299
                {
Dean@910
   300
                    for (int i = 0; i < msg.attachments.Length; i++)
Dean@910
   301
                    {
Dean@910
   302
                        newMessage.Attachments.Add(new PEPAttachment((blob)msg.attachments.GetValue(i)));
Dean@910
   303
                    }
Dean@910
   304
                }
Dean@910
   305
Dean@910
   306
                // BCC
Dean@910
   307
                newMessage.BCC.Clear();
Dean@910
   308
                if (msg.bcc != null)
Dean@910
   309
                {
Dean@910
   310
                    for (int i = 0; i < msg.bcc.Length; i++)
Dean@910
   311
                    {
Dean@910
   312
                        newMessage.BCC.Add(new PEPIdentity((pEp_identity_s)msg.bcc.GetValue(i)));
Dean@910
   313
                    }
Dean@910
   314
                }
Dean@910
   315
Dean@910
   316
                // CC
Dean@910
   317
                newMessage.CC.Clear();
Dean@910
   318
                if (msg.cc != null)
Dean@910
   319
                {
Dean@910
   320
                    for (int i = 0; i < msg.cc.Length; i++)
Dean@910
   321
                    {
Dean@910
   322
                        newMessage.CC.Add(new PEPIdentity((pEp_identity_s)msg.cc.GetValue(i)));
Dean@910
   323
                    }
Dean@910
   324
                }
Dean@910
   325
Dean@910
   326
                newMessage.Direction = msg.dir;
Dean@910
   327
                newMessage.From = new PEPIdentity(msg.from);
Dean@910
   328
                newMessage.ID = msg.id;
Dean@910
   329
Dean@910
   330
                // Keywords
Dean@910
   331
                newMessage.Keywords.Clear();
Dean@910
   332
                if (msg.keywords != null)
Dean@910
   333
                {
Dean@910
   334
                    for (int i = 0; i < msg.keywords.Length; i++)
Dean@910
   335
                    {
Dean@910
   336
                        newMessage.Keywords.Add((string)msg.keywords.GetValue(i));
Dean@910
   337
                    }
Dean@910
   338
                }
Dean@910
   339
Dean@910
   340
                newMessage.LongMsg = msg.longmsg;
Dean@910
   341
                newMessage.LongMsgFormattedHTML = msg.longmsg_formatted;
Dean@910
   342
                newMessage.LongMsgFormattedRTF = null;
Dean@910
   343
Dean@910
   344
                // Optional properties
Dean@910
   345
                newMessage.OptionalProperties.Clear();
Dean@910
   346
                if (msg.opt_fields != null)
Dean@910
   347
                {
Dean@910
   348
                    for (int i = 0; i < msg.opt_fields.Length; i++)
Dean@910
   349
                    {
Dean@910
   350
                        newMessage.OptionalProperties.Add((opt_field)msg.opt_fields.GetValue(i));
Dean@910
   351
                    }
Dean@910
   352
                }
Dean@910
   353
Dean@910
   354
                // ReceivedOn
Dean@910
   355
                if (msg.recv > 0)
Dean@910
   356
                {
Dean@910
   357
                    newMessage.ReceivedOn = new DateTime(1970, 1, 1).AddSeconds(msg.recv);
Dean@910
   358
                }
Dean@910
   359
                else
Dean@910
   360
                {
Dean@910
   361
                    newMessage.ReceivedOn = null;
Dean@910
   362
                }
Dean@910
   363
Dean@910
   364
                // SentOn
Dean@910
   365
                if (msg.sent > 0)
Dean@910
   366
                {
Dean@910
   367
                    newMessage.SentOn = new DateTime(1970, 1, 1).AddSeconds(msg.sent);
Dean@910
   368
                }
Dean@910
   369
                else
Dean@910
   370
                {
Dean@910
   371
                    newMessage.SentOn = null;
Dean@910
   372
                }
Dean@910
   373
Dean@910
   374
                newMessage.ShortMsg = msg.shortmsg;
Dean@910
   375
Dean@910
   376
                // To
Dean@910
   377
                newMessage.To.Clear();
Dean@910
   378
                if (msg.to != null)
Dean@910
   379
                {
Dean@910
   380
                    for (int i = 0; i < msg.to.Length; i++)
Dean@910
   381
                    {
Dean@910
   382
                        newMessage.To.Add(new PEPIdentity((pEp_identity_s)msg.to.GetValue(i)));
Dean@910
   383
                    }
Dean@910
   384
                }
Dean@910
   385
            }
Dean@910
   386
            catch (Exception ex)
Dean@910
   387
            {
Dean@910
   388
                status = Globals.ReturnStatus.Failure;
Dean@910
   389
                Globals.Log("PEPMessage.Create: Failure occured, " + ex.ToString());
Dean@910
   390
            }
Dean@910
   391
Dean@910
   392
            createdMessage = newMessage;
Dean@910
   393
            return (status);
Dean@910
   394
        }
Dean@910
   395
Dean@910
   396
        /// <summary>
Dean@910
   397
        /// Contructs a new message from the given outlook mail item.
Dean@910
   398
        /// The output will never be null.
Dean@910
   399
        /// </summary>
Dean@910
   400
        /// <param name="omi">The outlook mail item to create the message from.</param>
Dean@910
   401
        /// <param name="createdMessage">The output newly created message (will never be null).</param>
Dean@910
   402
        /// <param name="createWithoutContent">Whether to include content such as text body, attachments 
Dean@910
   403
        /// and optional properties.</param>
Dean@910
   404
        /// <returns>The status of the method.</returns>
Dean@910
   405
        public static Globals.ReturnStatus Create(Outlook.MailItem omi,
Dean@910
   406
                                                  out PEPMessage createdMessage,
Dean@910
   407
                                                  bool createWithoutContent = false)
Dean@910
   408
        {
Dean@910
   409
            byte[] rtfBody;
Dean@910
   410
            string delim;
Dean@910
   411
            string[] keywords;
Dean@910
   412
            object propertyValue;
Dean@910
   413
            opt_field newProp;
Dean@910
   414
            DateTime? receivedOn = null;
Dean@910
   415
            DateTime? sentOn = null;
Dean@910
   416
            PEPIdentity ident;
Dean@910
   417
            Outlook.Attachment currAttachment = null;
Dean@910
   418
            Outlook.Attachments attachments = null;
Dean@910
   419
            Outlook.Recipient currRecipient = null;
Dean@910
   420
            Outlook.Recipients recipients = null;
Dean@910
   421
            Globals.ReturnStatus status = Globals.ReturnStatus.Success;
Dean@910
   422
            Globals.ReturnStatus sts;
Dean@910
   423
            PEPMessage newMessage = new PEPMessage();
Dean@910
   424
Dean@910
   425
            try
Dean@910
   426
            {
Dean@910
   427
                Globals.LogVerbose("PEPMessage.Create: Creating new PEPMessage from OMI started, calculating recipients.");
Dean@910
   428
Dean@910
   429
                // Calculate recipients
Dean@910
   430
                newMessage.BCC.Clear();
Dean@910
   431
                newMessage.CC.Clear();
Dean@910
   432
                newMessage.To.Clear();
Dean@910
   433
                recipients = omi.Recipients;
Dean@910
   434
                for (int i = 1; i <= recipients.Count; i++)
Dean@910
   435
                {
Dean@910
   436
                    currRecipient = recipients[i];
Dean@910
   437
Dean@910
   438
                    switch ((Outlook.OlMailRecipientType)currRecipient.Type)
Dean@910
   439
                    {
Dean@910
   440
                        case Outlook.OlMailRecipientType.olBCC:
Dean@910
   441
Dean@910
   442
                            sts = PEPIdentity.ToIdentity(currRecipient, out ident);
Dean@910
   443
                            if (sts == Globals.ReturnStatus.Success)
Dean@910
   444
                            {
Dean@910
   445
                                newMessage.BCC.Add(ident);
Dean@910
   446
                            }
Dean@910
   447
                            else
Dean@910
   448
                            {
Dean@910
   449
                                // Update the status, only the first failure type is recorded
Dean@910
   450
                                if (status == Globals.ReturnStatus.Success)
Dean@910
   451
                                {
Dean@910
   452
                                    status = sts;
Dean@910
   453
                                }
Dean@910
   454
                            }
Dean@910
   455
Dean@910
   456
                            break;
Dean@910
   457
                        case Outlook.OlMailRecipientType.olCC:
Dean@910
   458
Dean@910
   459
                            sts = PEPIdentity.ToIdentity(currRecipient, out ident);
Dean@910
   460
                            if (sts == Globals.ReturnStatus.Success)
Dean@910
   461
                            {
Dean@910
   462
                                newMessage.CC.Add(ident);
Dean@910
   463
                            }
Dean@910
   464
                            else
Dean@910
   465
                            {
Dean@910
   466
                                // Update the status, only the first failure type is recorded
Dean@910
   467
                                if (status == Globals.ReturnStatus.Success)
Dean@910
   468
                                {
Dean@910
   469
                                    status = sts;
Dean@910
   470
                                }
Dean@910
   471
                            }
Dean@910
   472
Dean@910
   473
                            break;
Dean@910
   474
                        case Outlook.OlMailRecipientType.olTo:
Dean@910
   475
Dean@910
   476
                            sts = PEPIdentity.ToIdentity(currRecipient, out ident);
Dean@910
   477
                            if (sts == Globals.ReturnStatus.Success)
Dean@910
   478
                            {
Dean@910
   479
                                newMessage.To.Add(ident);
Dean@910
   480
                            }
Dean@910
   481
                            else
Dean@910
   482
                            {
Dean@910
   483
                                // Update the status, only the first failure type is recorded
Dean@910
   484
                                if (status == Globals.ReturnStatus.Success)
Dean@910
   485
                                {
Dean@910
   486
                                    status = sts;
Dean@910
   487
                                }
Dean@910
   488
                            }
Dean@910
   489
Dean@910
   490
                            break;
Dean@910
   491
                    }
Dean@910
   492
Dean@910
   493
                    Marshal.ReleaseComObject(currRecipient);
Dean@910
   494
                    currRecipient = null;
Dean@910
   495
                }
Dean@910
   496
Dean@910
   497
                Globals.LogVerbose("PEPMessage.Create: Recipients calculated, calculating main properties.");
Dean@910
   498
Dean@910
   499
                newMessage.Direction = CryptableMailItem.GetIsIncoming(omi) ? _pEp_msg_direction.pEp_dir_incoming : _pEp_msg_direction.pEp_dir_outgoing;
Dean@910
   500
Dean@910
   501
                // From
Dean@910
   502
                sts = PEPIdentity.GetFromIdentity(omi, out ident);
Dean@910
   503
                if (sts == Globals.ReturnStatus.Success)
Dean@910
   504
                {
Dean@910
   505
                    newMessage.From = ident;
Dean@910
   506
                }
Dean@910
   507
                else
Dean@910
   508
                {
Dean@910
   509
                    // Update the status, only the first failure type is recorded
Dean@910
   510
                    if (status == Globals.ReturnStatus.Success)
Dean@910
   511
                    {
Dean@910
   512
                        status = sts;
Dean@910
   513
                    }
Dean@910
   514
                }
Dean@910
   515
Dean@910
   516
                newMessage.ID = (string)MAPIHelper.GetProperty(omi, MAPIProperty.PidTagInternetMessageId, "");
Dean@910
   517
                newMessage.ShortMsg = omi.Subject;
Dean@910
   518
Dean@910
   519
                /* Date & Times
Dean@910
   520
                 * 
Dean@910
   521
                 * Note: The mail item date can be invalid:
Dean@910
   522
                 * For incoming this commonly occurs when creating a mirror -- it's created without a received time.
Dean@910
   523
                 * For outgoing this commonly occurs for unsent mail.
Dean@910
   524
                 * In these cases, the invalid date and time will be returned as 1/1/4501 at 12:00AM
Dean@910
   525
                 * This situation is filtered here and the date is set as null.
Dean@910
   526
                 */
Dean@910
   527
                receivedOn = omi.ReceivedTime;
Dean@910
   528
                if ((receivedOn != null) &&
Dean@910
   529
                    (((DateTime)receivedOn).Year > 4000)) // ~2000 years from now, no issue
Dean@910
   530
                {
Dean@910
   531
                    receivedOn = null;
Dean@910
   532
                }
Dean@910
   533
                newMessage.ReceivedOn = receivedOn;
Dean@910
   534
Dean@910
   535
                sentOn = omi.SentOn;
Dean@910
   536
                if ((sentOn != null) &&
Dean@910
   537
                    (((DateTime)sentOn).Year > 4000)) // ~2000 years from now, no issue
Dean@910
   538
                {
Dean@910
   539
                    sentOn = null;
Dean@910
   540
                }
Dean@910
   541
                newMessage.SentOn = sentOn;
Dean@910
   542
Dean@910
   543
                Globals.LogVerbose("PEPMessage.Create: Main properties calculated, calculating body and attachments.");
Dean@910
   544
Dean@910
   545
                // Calculate text body and attachments
Dean@910
   546
                if (createWithoutContent == false)
Dean@910
   547
                {
Dean@910
   548
                    // Body
Dean@910
   549
                    if (omi.Body != null)
Dean@910
   550
                    {
Dean@910
   551
                        newMessage.LongMsg = omi.Body.Replace("\r\n", "\n");
Dean@910
   552
Dean@910
   553
                        // Save as RTF
Dean@910
   554
                        try
Dean@910
   555
                        {
Dean@910
   556
                            rtfBody = omi.RTFBody;
Dean@910
   557
                            newMessage.LongMsgFormattedRTF = System.Text.Encoding.ASCII.GetString(rtfBody, 0, rtfBody.Length);
Dean@910
   558
                        }
Dean@910
   559
                        catch
Dean@910
   560
                        {
Dean@910
   561
                            Globals.Log("PEPMessage.Create: Unable to read RTF body in MailItem.");
Dean@910
   562
                        }
Dean@910
   563
Dean@910
   564
                        // Force rich text into HTML
Dean@910
   565
                        // WARNING: This is technically a modifcation of the original MailItem
Dean@910
   566
                        // It should be further investigated if this can be removed in the future.
Dean@910
   567
                        if (omi.BodyFormat == Outlook.OlBodyFormat.olFormatRichText)
Dean@910
   568
                        {
Dean@910
   569
                            omi.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
Dean@910
   570
                        }
Dean@910
   571
Dean@910
   572
                        if (omi.BodyFormat == Outlook.OlBodyFormat.olFormatHTML)
Dean@910
   573
                        {
Dean@910
   574
                            newMessage.LongMsgFormattedHTML = omi.HTMLBody;
Dean@910
   575
                        }
Dean@910
   576
                    }
Dean@910
   577
Dean@910
   578
                    // Attachments
Dean@910
   579
                    newMessage.Attachments.Clear();
Dean@910
   580
                    attachments = omi.Attachments;
Dean@910
   581
                    for (int i = 1; i <= attachments.Count; i++)
Dean@910
   582
                    {
Dean@910
   583
                        currAttachment = attachments[i];
Dean@910
   584
Dean@910
   585
                        try
Dean@910
   586
                        {
Dean@910
   587
                            newMessage.Attachments.Add(new PEPAttachment(currAttachment));
Dean@910
   588
                        }
Dean@910
   589
                        catch { }
Dean@910
   590
Dean@910
   591
                        Marshal.ReleaseComObject(currAttachment);
Dean@910
   592
                        currAttachment = null;
Dean@910
   593
                    }
Dean@910
   594
Dean@910
   595
                    // Keywords
Dean@910
   596
                    if (omi.Categories != null)
Dean@910
   597
                    {
Dean@910
   598
                        try
Dean@910
   599
                        {
Dean@910
   600
                            newMessage.Keywords.Clear();
Dean@910
   601
Dean@910
   602
                            using (RegistryKey key1 = Registry.CurrentUser.OpenSubKey("Control Panel\\International"))
Dean@910
   603
                            {
Dean@910
   604
                                delim = key1.GetValue("sList").ToString();
Dean@910
   605
                                keywords = omi.Categories.Split(delim.ToCharArray());
Dean@910
   606
Dean@910
   607
                                for (int i = 0; i < keywords.Length; i++)
Dean@910
   608
                                {
Dean@910
   609
                                    newMessage.Keywords.Add(keywords[i]);
Dean@910
   610
                                }
Dean@910
   611
                            }
Dean@910
   612
                        }
Dean@910
   613
                        catch
Dean@910
   614
                        {
Dean@910
   615
                            newMessage.Keywords.Clear();
Dean@910
   616
                            Globals.Log("PEPMessage.Create: Unable to set keywords.");
Dean@910
   617
                        }
Dean@910
   618
                    }
Dean@910
   619
Dean@910
   620
                    // Optional properties
Dean@910
   621
                    newMessage.OptionalProperties.Clear();
Dean@910
   622
Dean@910
   623
                    propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_ENC_STATUS);
Dean@910
   624
                    if (propertyValue != null)
Dean@910
   625
                    {
Dean@910
   626
                        newProp = new opt_field();
Dean@910
   627
                        newProp.name = PEPMessage.PR_X_ENC_STATUS_NAME;
Dean@910
   628
                        newProp.value = propertyValue.ToString();
Dean@910
   629
Dean@910
   630
                        newMessage.OptionalProperties.Add(newProp);
Dean@910
   631
                    }
Dean@910
   632
Dean@910
   633
                    propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_KEY_LIST);
Dean@910
   634
                    if (propertyValue != null)
Dean@910
   635
                    {
Dean@910
   636
                        newProp = new opt_field();
Dean@910
   637
                        newProp.name = PEPMessage.PR_X_KEY_LIST_NAME;
Dean@910
   638
                        newProp.value = propertyValue.ToString();
Dean@910
   639
Dean@910
   640
                        newMessage.OptionalProperties.Add(newProp);
Dean@910
   641
                    }
Dean@910
   642
Dean@910
   643
                    propertyValue = MAPIHelper.GetProperty(omi, PEPMessage.PR_X_PEP_VERSION);
Dean@910
   644
                    if (propertyValue != null)
Dean@910
   645
                    {
Dean@910
   646
                        newProp = new opt_field();
Dean@910
   647
                        newProp.name = PEPMessage.PR_X_PEP_VERSION_NAME;
Dean@910
   648
                        newProp.value = propertyValue.ToString();
Dean@910
   649
Dean@910
   650
                        newMessage.OptionalProperties.Add(newProp);
Dean@910
   651
                    }
Dean@910
   652
                }
Dean@910
   653
Dean@910
   654
                Globals.LogVerbose("PEPMessage.Create: New PEPMessage created from OMI.");
Dean@910
   655
            }
Dean@910
   656
            catch (Exception ex)
Dean@910
   657
            {
Dean@910
   658
                status = Globals.ReturnStatus.Failure;
Dean@910
   659
                Globals.Log("PEPMessage.Create: failure occured, " + ex.ToString());
Dean@910
   660
            }
Dean@910
   661
            finally
Dean@910
   662
            {
Dean@910
   663
                // Free resources
Dean@910
   664
                if (currAttachment != null)
Dean@910
   665
                {
Dean@910
   666
                    Marshal.ReleaseComObject(currAttachment);
Dean@910
   667
                    currAttachment = null;
Dean@910
   668
                }
Dean@910
   669
Dean@910
   670
                if (attachments != null)
Dean@910
   671
                {
Dean@910
   672
                    Marshal.ReleaseComObject(attachments);
Dean@910
   673
                    attachments = null;
Dean@910
   674
                }
Dean@910
   675
Dean@910
   676
                if (currRecipient != null)
Dean@910
   677
                {
Dean@910
   678
                    Marshal.ReleaseComObject(currRecipient);
Dean@910
   679
                    currRecipient = null;
Dean@910
   680
                }
Dean@910
   681
Dean@910
   682
                if (recipients != null)
Dean@910
   683
                {
Dean@910
   684
                    Marshal.ReleaseComObject(recipients);
Dean@910
   685
                    recipients = null;
Dean@910
   686
                }
Dean@910
   687
            }
Dean@910
   688
Dean@910
   689
            createdMessage = newMessage;
Dean@910
   690
            return (status);
Dean@910
   691
        }
Dean@910
   692
Dean@910
   693
        /// <summary>
Dean@384
   694
        /// Returns this pEp message as a new pEp engine text_message.
Dean@910
   695
        /// Warning: Any identity members (groups) are lost, call FlattenAllRecipientIdentities() before this method.
Dean@384
   696
        /// </summary>
Dean@384
   697
        /// <returns>A pEp engine identity.</returns>
Dean@384
   698
        public text_message ToCOMType()
Dean@384
   699
        {
Dean@384
   700
            List<blob> attachments = new List<blob>();
Dean@384
   701
            List<pEp_identity_s> bcc = new List<pEp_identity_s>();
Dean@384
   702
            List<pEp_identity_s> cc = new List<pEp_identity_s>();
Dean@384
   703
            List<pEp_identity_s> to = new List<pEp_identity_s>();
Dean@384
   704
            text_message result = new text_message();
Dean@384
   705
Dean@388
   706
            // Convert attachments
Dean@384
   707
            for (int i = 0; i < this._Attachments.Count; i++)
Dean@384
   708
            {
Dean@384
   709
                attachments.Add(this._Attachments[i].ToCOMType());
Dean@384
   710
            }
Dean@398
   711
Dean@388
   712
            // Convert BCC
Dean@384
   713
            for (int i = 0; i < this._BCC.Count; i++)
Dean@384
   714
            {
Dean@384
   715
                bcc.Add(this._BCC[i].ToCOMType());
Dean@384
   716
            }
Dean@398
   717
Dean@388
   718
            // Convert CC
Dean@384
   719
            for (int i = 0; i < this._CC.Count; i++)
Dean@384
   720
            {
Dean@384
   721
                cc.Add(this._CC[i].ToCOMType());
Dean@384
   722
            }
Dean@398
   723
Dean@388
   724
            // Convert To
Dean@388
   725
            for (int i = 0; i < this._To.Count; i++)
Dean@388
   726
            {
Dean@388
   727
                to.Add(this._To[i].ToCOMType());
Dean@388
   728
            }
Dean@388
   729
Dean@697
   730
            /* Set properties
Dean@697
   731
             * 
Dean@697
   732
             * Note: Skip DateTimeSentOrReceived and LongMsgFormattedRTF which
Dean@697
   733
             * are not supported in the pEp engine.
Dean@697
   734
             */
Dean@388
   735
            result.attachments = attachments.ToArray();
Dean@388
   736
            result.bcc = bcc.ToArray();
Dean@384
   737
            result.cc = cc.ToArray();
Dean@384
   738
            result.dir = this._Direction;
Dean@384
   739
            result.from = (this._From == null ? new pEp_identity_s() : this._From.ToCOMType());
Dean@384
   740
            result.id = this._ID;
Dean@384
   741
            result.keywords = this._Keywords.ToArray();
Dean@384
   742
            result.longmsg = this._LongMsg;
Dean@697
   743
            result.longmsg_formatted = this._LongMsgFormattedHTML;
Dean@572
   744
            result.opt_fields = this._OptionalProperties.ToArray();
Dean@384
   745
            result.shortmsg = this._ShortMsg;
Dean@384
   746
            result.to = to.ToArray();
Dean@384
   747
Dean@384
   748
            return (result);
Dean@384
   749
        }
Dean@384
   750
Dean@384
   751
        /// <summary>
Dean@389
   752
        /// Gets a deep copy of the object and all it's data.
Dean@389
   753
        /// </summary>
Dean@389
   754
        /// <returns>The deep copy of the object.</returns>
Dean@389
   755
        public PEPMessage Copy()
Dean@389
   756
        {
Dean@390
   757
            return (this.Copy(false));
Dean@390
   758
        }
Dean@390
   759
Dean@390
   760
        /// <summary>
Dean@390
   761
        /// Gets a copy of the PEPMessage with or without data.
Dean@390
   762
        /// </summary>
Dean@586
   763
        /// <param name="createWithoutContent">Whether to include content such as text body, attachments 
Dean@586
   764
        /// and optional properties.</param>
Dean@390
   765
        /// <returns>The copy of the PEPMessage.</returns>
Dean@390
   766
        public PEPMessage Copy(bool createWithoutContent = false)
Dean@390
   767
        {
Dean@389
   768
            PEPMessage copy = new PEPMessage();
Dean@389
   769
Dean@389
   770
            // Attachments
Dean@389
   771
            copy.Attachments.Clear();
Dean@390
   772
            if (createWithoutContent == false)
Dean@389
   773
            {
Dean@390
   774
                for (int i = 0; i < this._Attachments.Count; i++)
Dean@390
   775
                {
Dean@390
   776
                    copy.Attachments.Add(this._Attachments[i].Copy());
Dean@390
   777
                }
Dean@389
   778
            }
Dean@389
   779
Dean@389
   780
            // BCC
Dean@389
   781
            copy.BCC.Clear();
Dean@389
   782
            for (int i = 0; i < this._BCC.Count; i++)
Dean@389
   783
            {
Dean@389
   784
                copy.BCC.Add(this._BCC[i].Copy());
Dean@389
   785
            }
Dean@389
   786
Dean@389
   787
            // CC
Dean@389
   788
            copy.CC.Clear();
Dean@389
   789
            for (int i = 0; i < this._CC.Count; i++)
Dean@389
   790
            {
Dean@389
   791
                copy.CC.Add(this._CC[i].Copy());
Dean@389
   792
            }
Dean@389
   793
Dean@389
   794
            copy.Direction = this._Direction;
Dean@389
   795
            copy.From = (this._From == null ? null : this._From.Copy());
Dean@389
   796
            copy.ID = this._ID;
Dean@389
   797
Dean@389
   798
            // Keywords
Dean@389
   799
            copy.Keywords.Clear();
Dean@389
   800
            for (int i = 0; i < this._Keywords.Count; i++)
Dean@389
   801
            {
Dean@389
   802
                copy.Keywords.Add(this._Keywords[i]);
Dean@389
   803
            }
Dean@398
   804
Dean@390
   805
            // Body
Dean@390
   806
            if (createWithoutContent == false)
Dean@390
   807
            {
Dean@390
   808
                copy.LongMsg = this._LongMsg;
Dean@697
   809
                copy.LongMsgFormattedHTML = this._LongMsgFormattedHTML;
Dean@697
   810
                copy.LongMsgFormattedRTF = this._LongMsgFormattedRTF;
Dean@390
   811
            }
Dean@390
   812
            else
Dean@390
   813
            {
Dean@390
   814
                copy.LongMsg = null;
Dean@697
   815
                copy.LongMsgFormattedHTML = null;
Dean@697
   816
                copy.LongMsgFormattedRTF = null;
Dean@390
   817
            }
Dean@389
   818
Dean@389
   819
            // OptionalFields
Dean@572
   820
            copy.OptionalProperties.Clear();
Dean@586
   821
            if (createWithoutContent == false)
Dean@389
   822
            {
Dean@586
   823
                for (int i = 0; i < this._OptionalProperties.Count; i++)
Dean@586
   824
                {
Dean@586
   825
                    copy.OptionalProperties.Add(this._OptionalProperties[i]);
Dean@586
   826
                }
Dean@389
   827
            }
Dean@604
   828
Dean@721
   829
            // ReceivedOn
Dean@721
   830
            if (this._ReceivedOn != null)
Dean@721
   831
            {
Dean@721
   832
                copy.ReceivedOn = new DateTime(((DateTime)this._ReceivedOn).Ticks);
Dean@721
   833
            }
Dean@721
   834
            else
Dean@721
   835
            {
Dean@721
   836
                copy.ReceivedOn = null;
Dean@721
   837
            }
Dean@721
   838
Dean@721
   839
            // SentOn
Dean@721
   840
            if (this._SentOn != null)
Dean@721
   841
            {
Dean@721
   842
                copy.SentOn = new DateTime(((DateTime)this._SentOn).Ticks);
Dean@721
   843
            }
Dean@721
   844
            else
Dean@721
   845
            {
Dean@721
   846
                copy.SentOn = null;
Dean@721
   847
            }
Dean@721
   848
Dean@389
   849
            copy.ShortMsg = this._ShortMsg;
Dean@389
   850
Dean@389
   851
            // To
Dean@389
   852
            copy.To.Clear();
Dean@389
   853
            for (int i = 0; i < this._To.Count; i++)
Dean@389
   854
            {
Dean@389
   855
                copy.To.Add(this._To[i].Copy());
Dean@389
   856
            }
Dean@389
   857
Dean@389
   858
            return (copy);
Dean@389
   859
        }
Dean@389
   860
Dean@389
   861
        /// <summary>
Dean@384
   862
        /// Applies this pEp message's data to the given Outlook item.
Dean@384
   863
        /// </summary>
Dean@384
   864
        /// <param name="omi">The Outlook mail item to apply this pEp message's data to.</param>
Dean@586
   865
        /// <param name="includeOptionalProperties">Whether to include optional properites such as 
Dean@586
   866
        /// color rating, pEp version etc...</param>
Dean@910
   867
        /// <returns>The status of the method.</returns>
Dean@910
   868
        public Globals.ReturnStatus ApplyTo(Outlook.MailItem omi,
Dean@910
   869
                                            bool includeOptionalProperties = false)
Dean@384
   870
        {
Dean@543
   871
            Outlook.Attachments attachments = null;
Dean@543
   872
            Outlook.Recipient newRecipient = null;
Dean@543
   873
            Outlook.Recipients recipients = null;
Dean@543
   874
            Outlook.Account currAccount = null;
Dean@543
   875
            Outlook.Account sendUsingAccount = null;
Dean@543
   876
            Outlook.Accounts accounts = null;
Dean@910
   877
            Globals.ReturnStatus status = Globals.ReturnStatus.Success;
Dean@408
   878
Dean@543
   879
            try
Dean@408
   880
            {
Dean@543
   881
                // Remove all recipients
Dean@543
   882
                recipients = omi.Recipients;
Dean@543
   883
                while (recipients.Count > 0)
Dean@543
   884
                {
Dean@543
   885
                    recipients.Remove(1);
Dean@543
   886
                }
Dean@543
   887
Dean@543
   888
                // Set recipients
Dean@543
   889
                for (int i = 0; i < this._BCC.Count; i++)
Dean@543
   890
                {
Dean@795
   891
                    if (string.IsNullOrWhiteSpace(this._BCC[i].Address) == false)
Dean@543
   892
                    {
Dean@795
   893
                        // Add by address
Dean@543
   894
                        newRecipient = recipients.Add(this._BCC[i].Address);
Dean@543
   895
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olBCC;
Dean@543
   896
Dean@543
   897
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   898
                        newRecipient = null;
Dean@543
   899
                    }
Dean@795
   900
                    else if (string.IsNullOrWhiteSpace(this._BCC[i].Username) == false)
Dean@795
   901
                    {
Dean@795
   902
                        // Add by username (required for distribution lists)
Dean@795
   903
                        newRecipient = recipients.Add(this._BCC[i].Username);
Dean@795
   904
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olBCC;
Dean@795
   905
Dean@795
   906
                        Marshal.ReleaseComObject(newRecipient);
Dean@795
   907
                        newRecipient = null;
Dean@795
   908
                    }
Dean@543
   909
                }
Dean@543
   910
Dean@543
   911
                for (int i = 0; i < this._CC.Count; i++)
Dean@543
   912
                {
Dean@795
   913
                    if (string.IsNullOrWhiteSpace(this._CC[i].Address) == false)
Dean@543
   914
                    {
Dean@795
   915
                        // Add by address
Dean@543
   916
                        newRecipient = recipients.Add(this._CC[i].Address);
Dean@543
   917
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olCC;
Dean@543
   918
Dean@543
   919
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   920
                        newRecipient = null;
Dean@543
   921
                    }
Dean@795
   922
                    else if (string.IsNullOrWhiteSpace(this._CC[i].Username) == false)
Dean@795
   923
                    {
Dean@795
   924
                        // Add by username (required for distribution lists)
Dean@795
   925
                        newRecipient = recipients.Add(this._CC[i].Username);
Dean@795
   926
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olCC;
Dean@795
   927
Dean@795
   928
                        Marshal.ReleaseComObject(newRecipient);
Dean@795
   929
                        newRecipient = null;
Dean@795
   930
                    }
Dean@543
   931
                }
Dean@543
   932
Dean@543
   933
                for (int i = 0; i < this._To.Count; i++)
Dean@543
   934
                {
Dean@795
   935
                    if (string.IsNullOrWhiteSpace(this._To[i].Address) == false)
Dean@543
   936
                    {
Dean@795
   937
                        // Add by address
Dean@543
   938
                        newRecipient = recipients.Add(this._To[i].Address);
Dean@543
   939
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olTo;
Dean@543
   940
Dean@543
   941
                        Marshal.ReleaseComObject(newRecipient);
Dean@543
   942
                        newRecipient = null;
Dean@543
   943
                    }
Dean@795
   944
                    else if (string.IsNullOrWhiteSpace(this._To[i].Username) == false)
Dean@795
   945
                    {
Dean@795
   946
                        // Add by username (required for distribution lists)
Dean@795
   947
                        newRecipient = recipients.Add(this._To[i].Username);
Dean@795
   948
                        newRecipient.Type = (int)Outlook.OlMailRecipientType.olTo;
Dean@795
   949
Dean@795
   950
                        Marshal.ReleaseComObject(newRecipient);
Dean@795
   951
                        newRecipient = null;
Dean@795
   952
                    }
Dean@543
   953
                }
Dean@543
   954
Dean@910
   955
                try
Dean@910
   956
                {
Dean@910
   957
                    recipients.ResolveAll();
Dean@910
   958
                }
Dean@910
   959
                catch { }
Dean@543
   960
Dean@543
   961
                /* Set sender
Dean@543
   962
                 * Note that if fails, will be empty which eventually will use the default send account
Dean@543
   963
                 * If the send using account is already populated, this cannot be re-set.
Dean@543
   964
                 * So far this doesn't appear to be an issue as it occurs when applying unencrypted data to a mirror.
Dean@543
   965
                 * However, the mirror SendUsingAccount is already correct at this point and doesn't need to be set.
Dean@543
   966
                 */
Dean@543
   967
                sendUsingAccount = omi.SendUsingAccount;
Dean@543
   968
Dean@543
   969
                if ((this._From != null) &&
Dean@543
   970
                    (this._From.Address != null) &&
Dean@543
   971
                    (sendUsingAccount == null))
Dean@543
   972
                {
Dean@543
   973
                    accounts = Globals.ThisAddIn.Application.Session.Accounts;
Dean@543
   974
Dean@543
   975
                    // Note: Index starts at 1
Dean@543
   976
                    for (int i = 1; i <= accounts.Count; i++)
Dean@543
   977
                    {
Dean@543
   978
                        currAccount = accounts[i];
Dean@543
   979
Dean@543
   980
                        if ((currAccount.SmtpAddress != null) &&
Dean@543
   981
                            (currAccount.SmtpAddress.ToUpper() == this._From.Address.ToUpper()))
Dean@543
   982
                        {
Dean@543
   983
                            /* Try to set the SendUsingAccount
Dean@543
   984
                             * This will fail if the mail item is already marked as sent or the SendUsingAccount is not null, etc...
Dean@564
   985
                             * If it fails, Outlook will in the end just use the default account.
Dean@564
   986
                             * This property should ideally be set before a mail item is saved.
Dean@543
   987
                             */
Dean@543
   988
                            try
Dean@543
   989
                            {
Dean@564
   990
                                omi.SendUsingAccount = currAccount;
Dean@543
   991
                            }
Dean@543
   992
                            catch { }
Dean@543
   993
Dean@543
   994
                            Marshal.ReleaseComObject(currAccount);
Dean@543
   995
                            currAccount = null;
Dean@543
   996
Dean@543
   997
                            break;
Dean@543
   998
                        }
Dean@543
   999
Dean@543
  1000
                        Marshal.ReleaseComObject(currAccount);
Dean@543
  1001
                        currAccount = null;
Dean@543
  1002
                    }
Dean@543
  1003
                }
Dean@543
  1004
Dean@543
  1005
                // Set the subject
Dean@543
  1006
                omi.Subject = this._ShortMsg;
Dean@543
  1007
Dean@697
  1008
                // Set the body (skip RTF format, only use HTML which is what the engine uses)
Dean@697
  1009
                if (string.IsNullOrWhiteSpace(this._LongMsgFormattedHTML))
Dean@543
  1010
                {
Dean@543
  1011
                    omi.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
Dean@543
  1012
                    omi.Body = this._LongMsg;
Dean@543
  1013
                }
Dean@543
  1014
                else
Dean@543
  1015
                {
Dean@543
  1016
                    omi.BodyFormat = Outlook.OlBodyFormat.olFormatHTML;
Dean@697
  1017
                    omi.HTMLBody = this._LongMsgFormattedHTML;
Dean@543
  1018
                }
Dean@543
  1019
Dean@754
  1020
                /* Set the encoding to UTF-8
Dean@754
  1021
                 * See: https://msdn.microsoft.com/en-us/library/office/ff860730.aspx
Dean@754
  1022
                 * All PEPMessages should be UTF even those coming from the engine.
Dean@754
  1023
                 */
Dean@754
  1024
                try
Dean@754
  1025
                {
Dean@790
  1026
                    MAPIHelper.SetProperty(omi, MAPIProperty.PidTagInternetCodepage, 65001);
Dean@790
  1027
                    MAPIHelper.SetProperty(omi, MAPIProperty.PidTagMessageCodepage, 65001);
Dean@754
  1028
                }
Dean@754
  1029
                catch
Dean@754
  1030
                {
Dean@860
  1031
                    Globals.Log("PEPMessage.ApplyTo: Failed to set UTF-8 encoding.");
Dean@754
  1032
                }
Dean@754
  1033
Dean@543
  1034
                // Remove any previous attachments
Dean@543
  1035
                attachments = omi.Attachments;
Dean@543
  1036
                while (attachments.Count > 0)
Dean@543
  1037
                {
Dean@543
  1038
                    attachments.Remove(1);
Dean@543
  1039
                }
Dean@543
  1040
Dean@543
  1041
                // Add new attachments
Dean@543
  1042
                for (int i = 0; i < this._Attachments.Count; i++)
Dean@543
  1043
                {
Dean@843
  1044
                    this._Attachments[i].AddTo(attachments, ("attachment" + i.ToString()));
Dean@543
  1045
                }
Dean@543
  1046
Dean@572
  1047
                // Optional properties
Dean@586
  1048
                if (includeOptionalProperties)
Dean@543
  1049
                {
Dean@586
  1050
                    for (int i = 0; i < this._OptionalProperties.Count; i++)
Dean@586
  1051
                    {
Dean@586
  1052
                        MAPIHelper.SetProperty(omi,
Dean@586
  1053
                                               PEPMessage.PR_OPT_FIELD + this._OptionalProperties[i].name,
Dean@586
  1054
                                               this._OptionalProperties[i].value);
Dean@586
  1055
                    }
Dean@543
  1056
                }
Dean@408
  1057
            }
Dean@545
  1058
            catch (Exception ex)
Dean@545
  1059
            {
Dean@910
  1060
                status = Globals.ReturnStatus.Failure;
Dean@910
  1061
                Globals.Log("PEPMessage.ApplyTo: Failure occured, " + ex.ToString());
Dean@545
  1062
            }
Dean@543
  1063
            finally
Dean@543
  1064
            {
Dean@543
  1065
                if (attachments != null)
Dean@466
  1066
                {
Dean@543
  1067
                    Marshal.ReleaseComObject(attachments);
Dean@543
  1068
                    attachments = null;
Dean@543
  1069
                }
Dean@408
  1070
Dean@543
  1071
                if (newRecipient != null)
Dean@543
  1072
                {
Dean@466
  1073
                    Marshal.ReleaseComObject(newRecipient);
Dean@543
  1074
                    newRecipient = null;
Dean@543
  1075
                }
Dean@543
  1076
Dean@543
  1077
                if (recipients != null)
Dean@543
  1078
                {
Dean@543
  1079
                    Marshal.ReleaseComObject(recipients);
Dean@543
  1080
                    recipients = null;
Dean@543
  1081
                }
Dean@543
  1082
Dean@543
  1083
                if (currAccount != null)
Dean@543
  1084
                {
Dean@543
  1085
                    Marshal.ReleaseComObject(currAccount);
Dean@543
  1086
                    currAccount = null;
Dean@543
  1087
                }
Dean@543
  1088
Dean@543
  1089
                if (sendUsingAccount != null)
Dean@543
  1090
                {
Dean@543
  1091
                    Marshal.ReleaseComObject(sendUsingAccount);
Dean@543
  1092
                    sendUsingAccount = null;
Dean@543
  1093
                }
Dean@543
  1094
Dean@543
  1095
                if (accounts != null)
Dean@543
  1096
                {
Dean@543
  1097
                    Marshal.ReleaseComObject(accounts);
Dean@543
  1098
                    accounts = null;
Dean@543
  1099
                }
Dean@408
  1100
            }
Dean@408
  1101
Dean@910
  1102
            return (status);
Dean@384
  1103
        }
Dean@384
  1104
Dean@398
  1105
        /// <summary>
Dean@398
  1106
        /// Recursivley converts all "BCC", "CC", and "To" identities into a 'flat' list of any members.
Dean@398
  1107
        /// This will remove groups (hierarchy) and convert a group into it's members.
Dean@398
  1108
        /// </summary>
Dean@398
  1109
        public void FlattenAllRecipientIdentities()
Dean@398
  1110
        {
Dean@398
  1111
            this._BCC = PEPIdentity.ToFlatList(this._BCC);
Dean@398
  1112
            this._CC = PEPIdentity.ToFlatList(this._CC);
Dean@398
  1113
            this._To = PEPIdentity.ToFlatList(this._To);
Dean@398
  1114
Dean@398
  1115
            return;
Dean@398
  1116
        }
Dean@413
  1117
Dean@808
  1118
        /// <summary>
Dean@808
  1119
        /// Processes all content IDs in the image attachments as well as HTML body.
Dean@808
  1120
        /// This will convert the CID's to the image filename only.
Dean@808
  1121
        /// </summary>
Dean@808
  1122
        public void NormalizeContentIDs()
Dean@808
  1123
        {
Dean@808
  1124
            int currImgTagIndex;
Dean@808
  1125
            int currImgTagStopIndex;
Dean@808
  1126
            int currImgTagCIDIndex;
Dean@808
  1127
            int currImgTagCIDStopIndex;
Dean@920
  1128
            int tempIndex;
Dean@808
  1129
            string currCID;
Dean@808
  1130
            string newCID;
Dean@808
  1131
            string beginning;
Dean@808
  1132
            string ending;
Dean@808
  1133
            string currFileName;
Dean@808
  1134
            string workingHTML;
Dean@808
  1135
            Dictionary<string, string> modifiedCIDs = new Dictionary<string, string>();
Dean@808
  1136
Dean@808
  1137
            // Modify CIDs for all attachments and store modified CIDs in the dictionary
Dean@808
  1138
            for (int i = 0; i < this._Attachments.Count; i++)
Dean@808
  1139
            {
Dean@808
  1140
                currCID = this._Attachments[i].ContentID;
Dean@808
  1141
                currFileName = this._Attachments[i].FileName;
Dean@808
  1142
Dean@808
  1143
                if (string.IsNullOrEmpty(currCID))
Dean@808
  1144
                {
Dean@920
  1145
                    /* Just use the file name (even if file name is null or empty)
Dean@920
  1146
                     * It's doesn't matter as it shouldn't be replaced in HTML.
Dean@920
  1147
                     * This situation should mean either the attachment isn't an embedded image, or
Dean@920
  1148
                     * the filename is already used as the CID in the HTML.
Dean@920
  1149
                     */
Dean@808
  1150
                    newCID = currFileName;
Dean@808
  1151
                }
Dean@808
  1152
                else
Dean@808
  1153
                {
Dean@808
  1154
                    if (string.IsNullOrEmpty(currFileName))
Dean@808
  1155
                    {
Dean@808
  1156
                        // A name must exist for HTML so create one
Dean@808
  1157
                        newCID = "attachment" + i.ToString();
Dean@808
  1158
                    }
Dean@808
  1159
                    else
Dean@808
  1160
                    {
Dean@843
  1161
                        newCID = currFileName;
Dean@808
  1162
                    }
Dean@808
  1163
Dean@808
  1164
                    modifiedCIDs.Add(currCID, newCID);
Dean@808
  1165
                }
Dean@808
  1166
Dean@808
  1167
                this._Attachments[i].ContentID = newCID;
Dean@808
  1168
            }
Dean@808
  1169
Dean@808
  1170
            /* Process the HTML body replacing all modified CIDs
Dean@808
  1171
             * Since no HTML document library is provided in standard C#, text operations are done.
Dean@808
  1172
             * This should work ok, but there are some potential issue with malformed HTML that might render correctly.
Dean@808
  1173
             * Only " is supported instead of ' as well.
Dean@808
  1174
             * This shouldn't be an issue since the method is primarily run on mail items generated internally.
Dean@808
  1175
             */
Dean@808
  1176
            workingHTML = this._LongMsgFormattedHTML;
Dean@808
  1177
            if (string.IsNullOrEmpty(workingHTML) == false)
Dean@808
  1178
            {
Dean@920
  1179
                tempIndex = workingHTML.IndexOf("<img", 0);
Dean@920
  1180
                currImgTagIndex = (tempIndex > -1 ? (tempIndex + 4) : -1); // MUST start index after "<img"
Dean@808
  1181
Dean@808
  1182
                while (currImgTagIndex > -1)
Dean@808
  1183
                {
Dean@920
  1184
                    try
Dean@920
  1185
                    {
Dean@920
  1186
                        tempIndex = workingHTML.IndexOf("src=\"cid:", currImgTagIndex);
Dean@920
  1187
                        currImgTagCIDIndex = (tempIndex > -1 ? (tempIndex + 9) : -1);
Dean@920
  1188
                        currImgTagCIDStopIndex = workingHTML.IndexOf("\"", currImgTagCIDIndex);
Dean@920
  1189
                        currImgTagStopIndex = workingHTML.IndexOf(">", currImgTagIndex);
Dean@920
  1190
                    }
Dean@920
  1191
                    catch
Dean@920
  1192
                    {
Dean@920
  1193
                        Globals.Log("NormalizeContentIDs: Incorrect index detected when calculating CID position, skipping current img.");
Dean@920
  1194
Dean@920
  1195
                        // Likely System.ArgumentOutOfRangeException from incorrect index
Dean@920
  1196
                        // Just invalidate all locations and will not change this <img>
Dean@920
  1197
                        currImgTagCIDIndex = -1;
Dean@920
  1198
                        currImgTagCIDStopIndex = -1;
Dean@920
  1199
                        currImgTagStopIndex = -1;
Dean@920
  1200
                    }
Dean@843
  1201
Dean@808
  1202
                    // Validate relative index positions
Dean@808
  1203
                    if ((currImgTagCIDIndex < currImgTagStopIndex) &&
Dean@808
  1204
                        (currImgTagCIDStopIndex < currImgTagStopIndex) &&
Dean@808
  1205
                        ((currImgTagCIDStopIndex - currImgTagCIDIndex) >= 1))
Dean@808
  1206
                    {
Dean@808
  1207
                        // Split the HTML at the CID and modify if necessary
Dean@920
  1208
                        try
Dean@920
  1209
                        {
Dean@920
  1210
                            beginning = workingHTML.Substring(0, currImgTagCIDIndex);
Dean@920
  1211
                            ending = workingHTML.Substring(currImgTagCIDStopIndex);
Dean@920
  1212
                            currCID = workingHTML.Substring(currImgTagCIDIndex, (currImgTagCIDStopIndex - currImgTagCIDIndex));
Dean@920
  1213
                        }
Dean@920
  1214
                        catch
Dean@920
  1215
                        {
Dean@920
  1216
                            Globals.Log("NormalizeContentIDs: Error splitting HTML at CID, skipping current img.");
Dean@920
  1217
Dean@920
  1218
                            beginning = null;
Dean@920
  1219
                            ending = null;
Dean@920
  1220
                            currCID = null;
Dean@920
  1221
                        }
Dean@808
  1222
Dean@808
  1223
                        // Lookup the new CID
Dean@808
  1224
                        newCID = null;
Dean@808
  1225
                        try
Dean@808
  1226
                        {
Dean@920
  1227
                            if (currCID != null)
Dean@920
  1228
                            {
Dean@920
  1229
                                newCID = modifiedCIDs[currCID];
Dean@920
  1230
                            }
Dean@808
  1231
                        }
Dean@808
  1232
                        catch
Dean@808
  1233
                        {
Dean@808
  1234
                            newCID = null;
Dean@808
  1235
                        }
Dean@808
  1236
Dean@808
  1237
                        // Replace
Dean@920
  1238
                        if ((beginning != null) &&
Dean@920
  1239
                            (string.IsNullOrEmpty(newCID) == false) &&
Dean@920
  1240
                            (ending != null))
Dean@808
  1241
                        {
Dean@808
  1242
                            workingHTML = beginning + newCID + ending;
Dean@808
  1243
                        }
Dean@808
  1244
                    }
Dean@808
  1245
Dean@920
  1246
                    try
Dean@920
  1247
                    {
Dean@920
  1248
                        tempIndex = workingHTML.IndexOf("<img", currImgTagIndex);
Dean@920
  1249
                        currImgTagIndex = (tempIndex > -1 ? (tempIndex + 4) : -1); // MUST start index after "<img"
Dean@920
  1250
                    }
Dean@920
  1251
                    catch
Dean@920
  1252
                    {
Dean@920
  1253
                        Globals.Log("NormalizeContentIDs: Incorrect index detected, stopping calculation.");
Dean@920
  1254
Dean@920
  1255
                        // Likely System.ArgumentOutOfRangeException from incorrect index
Dean@920
  1256
                        // Stop processing the HTML and use whatever is processed up to this point
Dean@920
  1257
                        currImgTagIndex = -1;
Dean@920
  1258
                    }
Dean@808
  1259
                }
Dean@808
  1260
            }
Dean@808
  1261
            this._LongMsgFormattedHTML = workingHTML;
Dean@808
  1262
Dean@808
  1263
            return;
Dean@808
  1264
        }
Dean@384
  1265
    }
Dean@384
  1266
}