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