PEPIdentity.cs
author Thomas
Thu, 08 Jun 2017 17:21:10 +0200
changeset 1691 2f6abc7de8f1
parent 1516 0a838ded02dd
child 1730 dab4ab5b1143
permissions -rw-r--r--
Improve Exchange user detection in GetFromIdentity
Dean@384
     1
´╗┐using pEpCOMServerAdapterLib;
Dean@384
     2
using System;
Dean@1238
     3
using System.Collections.Generic;
Dean@1274
     4
using System.ComponentModel;
Dean@394
     5
using System.Linq;
Dean@384
     6
using System.Runtime.InteropServices;
Dean@1238
     7
using System.Text.RegularExpressions;
Dean@384
     8
using Outlook = Microsoft.Office.Interop.Outlook;
Dean@384
     9
Dean@384
    10
namespace pEp
Dean@384
    11
{
Dean@384
    12
    /// <summary>
Dean@384
    13
    /// Class to wrap the pEp engine identity and expose additional functionality.
Dean@384
    14
    /// </summary>
Dean@1274
    15
    internal class PEPIdentity : INotifyPropertyChanged,
Dean@1274
    16
                                 IEquatable<PEPIdentity>,
Dean@1238
    17
                                 Interfaces.ICopy<PEPIdentity>
Dean@384
    18
    {
Dean@1274
    19
        /// <summary>
Dean@1274
    20
        /// Event raised when a property is changed on a component.
Dean@1274
    21
        /// </summary>
Dean@1274
    22
        public event PropertyChangedEventHandler PropertyChanged;
Dean@1274
    23
Dean@760
    24
        private bool?             _IsForceUnencrypted;
Dean@1033
    25
        private bool              _IsSmartAddressEnabled;
Dean@394
    26
        private List<PEPIdentity> _Members;
Dean@1362
    27
        private pEpRating         _Rating;
Dean@384
    28
markus@1337
    29
        private pEpIdentity internalIdentity;
Dean@762
    30
Dean@384
    31
        /**************************************************************
Dean@384
    32
         * 
Dean@384
    33
         * Constructors
Dean@384
    34
         * 
Dean@384
    35
         *************************************************************/
Dean@384
    36
Dean@384
    37
        /// <summary>
Dean@384
    38
        /// Default constructor.
Dean@384
    39
        /// </summary>
Dean@384
    40
        public PEPIdentity()
Dean@384
    41
        {
markus@1337
    42
            this.internalIdentity = new pEpIdentity();
Dean@760
    43
            this._IsForceUnencrypted = null;
Dean@1033
    44
            this._IsSmartAddressEnabled = true;
Dean@394
    45
            this._Members = new List<PEPIdentity>();
Dean@1362
    46
            this._Rating = pEpRating.pEpRatingUndefined;
Dean@384
    47
        }
Dean@384
    48
Dean@384
    49
        /// <summary>
Dean@463
    50
        /// Constructor to build with the given address.
Dean@463
    51
        /// </summary>
Dean@463
    52
        /// <param name="address">The address of the identity to build with.</param>
Dean@463
    53
        public PEPIdentity(string address)
Dean@463
    54
        {
markus@1337
    55
            this.internalIdentity = new pEpIdentity();
markus@1347
    56
            this.internalIdentity.Address = address;
Dean@760
    57
            this._IsForceUnencrypted = null;
Dean@1033
    58
            this._IsSmartAddressEnabled = true;
Dean@463
    59
            this._Members = new List<PEPIdentity>();
Dean@1362
    60
            this._Rating = pEpRating.pEpRatingUndefined;
Dean@463
    61
        }
Dean@463
    62
Dean@463
    63
        /// <summary>
Dean@384
    64
        /// Constructor to build from a pEp engine identity.
Dean@384
    65
        /// </summary>
Dean@384
    66
        /// <param name="ident">The identity to build from.</param>
markus@1337
    67
        public PEPIdentity(pEpIdentity ident)
Dean@384
    68
        {
Dean@384
    69
            this.internalIdentity = ident;
Dean@760
    70
            this._IsForceUnencrypted = null;
Dean@1033
    71
            this._IsSmartAddressEnabled = true;
Dean@394
    72
            this._Members = new List<PEPIdentity>();
Dean@1362
    73
            this._Rating = pEpRating.pEpRatingUndefined;
Dean@384
    74
        }
Dean@384
    75
Dean@384
    76
        /**************************************************************
Dean@384
    77
         * 
Dean@384
    78
         * Property Accessors
Dean@384
    79
         * 
Dean@384
    80
         *************************************************************/
Dean@384
    81
Dean@384
    82
        /// <summary>
Dean@384
    83
        /// Gets or sets the email address of the identity.
Dean@1033
    84
        /// Note: For get, the address used is the smart address.
Dean@1348
    85
        /// If smart address is enabled, and the set address is empty/null, the user name is 
Dean@1033
    86
        /// considered the address if it's formatted as an address itself.
Dean@384
    87
        /// </summary>
Dean@384
    88
        public string Address
Dean@384
    89
        {
Dean@1033
    90
            get
Dean@1033
    91
            {
Dean@1033
    92
                // Make sure to use the smart address
Dean@1033
    93
                return (this.GetSmartAddress());
Dean@1033
    94
            }
Dean@1274
    95
            set
Dean@1274
    96
            {
markus@1347
    97
                this.internalIdentity.Address = value;
Dean@1274
    98
                this.RaisePropertyChangedEvent(nameof(this.Address));
Dean@1274
    99
                this.RaisePropertyChangedEvent(nameof(this.DisplayString));
Dean@1274
   100
                this.RaisePropertyChangedEvent(nameof(this.IsAddressValid));
Dean@1274
   101
            }
Dean@384
   102
        }
Dean@384
   103
Dean@384
   104
        /// <summary>
Dean@384
   105
        /// Gets or sets the communication type with the identity.
Dean@384
   106
        /// </summary>
markus@1337
   107
        public pEpComType CommunicationType
Dean@384
   108
        {
markus@1347
   109
            get { return (this.internalIdentity.CommType); }
Dean@1274
   110
            set
Dean@1274
   111
            {
markus@1347
   112
                this.internalIdentity.CommType = value;
Dean@1274
   113
                this.RaisePropertyChangedEvent(nameof(this.CommunicationType));
Dean@1274
   114
            }
Dean@1251
   115
        }
Dean@1251
   116
Dean@1251
   117
        /// <summary>
Dean@384
   118
        /// Gets or sets the pEp engine fingerprint of the identity.
Dean@384
   119
        /// </summary>
Dean@384
   120
        public string Fingerprint
Dean@384
   121
        {
Dean@384
   122
            get { return (this.internalIdentity.fpr); }
Dean@1274
   123
            set
Dean@1274
   124
            {
Dean@1274
   125
                this.internalIdentity.fpr = value;
Dean@1274
   126
                this.RaisePropertyChangedEvent(nameof(this.Fingerprint));
Dean@1274
   127
            }
Dean@384
   128
        }
Dean@384
   129
Dean@384
   130
        /// <summary>
Dean@1504
   131
        /// Gets or sets whether the identity is a member of an existing device group.
Dean@1504
   132
        /// </summary>
Dean@1504
   133
        public bool IsInDeviceGroup
Dean@1504
   134
        {
Dean@1504
   135
            get { return (this.internalIdentity.GetIsInDeviceGroup()); }
Dean@1504
   136
            set
Dean@1504
   137
            {
Dean@1504
   138
                if (value)
Dean@1504
   139
                {
Dean@1504
   140
                    this.internalIdentity.Flags |= pEpIdentityFlags.pEpIdfDevicegroup;
Dean@1504
   141
                }
Dean@1504
   142
                else
Dean@1504
   143
                {
Dean@1504
   144
                    this.internalIdentity.Flags &= ~pEpIdentityFlags.pEpIdfDevicegroup;
Dean@1504
   145
                }
Dean@1504
   146
Dean@1504
   147
                this.RaisePropertyChangedEvent(nameof(this.IsInDeviceGroup));
Dean@1504
   148
            }
Dean@1504
   149
        }
Dean@1504
   150
Dean@1504
   151
        /// <summary>
Dean@1504
   152
        /// Gets or sets whether the identity is a list.
Dean@1504
   153
        /// Email lists should not be used for syncronization.
Dean@1504
   154
        /// </summary>
Dean@1504
   155
        public bool IsList
Dean@1504
   156
        {
Dean@1504
   157
            get { return (this.internalIdentity.GetIsList()); }
Dean@1504
   158
            set
Dean@1504
   159
            {
Dean@1504
   160
                if (value)
Dean@1504
   161
                {
Dean@1504
   162
                    this.internalIdentity.Flags |= pEpIdentityFlags.pEpIdfList;
Dean@1504
   163
                }
Dean@1504
   164
                else
Dean@1504
   165
                {
Dean@1504
   166
                    this.internalIdentity.Flags &= ~pEpIdentityFlags.pEpIdfList;
Dean@1504
   167
                }
Dean@1504
   168
Dean@1504
   169
                this.RaisePropertyChangedEvent(nameof(this.IsList));
Dean@1504
   170
            }
Dean@1504
   171
        }
Dean@1504
   172
Dean@1504
   173
        /// <summary>
Dean@1504
   174
        /// Gets or sets whether the identity is to be included in device synchronization.
Dean@1504
   175
        /// </summary>
Dean@1504
   176
        public bool IsSyncEnabled
Dean@1504
   177
        {
Dean@1504
   178
            get { return (this.internalIdentity.GetIsSyncEnabled()); }
Dean@1504
   179
            set
Dean@1504
   180
            {
Dean@1504
   181
                if (value)
Dean@1504
   182
                {
Dean@1504
   183
                    // Note: Invert the logic
Dean@1504
   184
                    this.internalIdentity.Flags &= ~pEpIdentityFlags.pEpIdfNotForSync;
Dean@1504
   185
                }
Dean@1504
   186
                else
Dean@1504
   187
                {
Dean@1504
   188
                    this.internalIdentity.Flags |= pEpIdentityFlags.pEpIdfNotForSync;
Dean@1504
   189
                }
Dean@1504
   190
Dean@1504
   191
                this.RaisePropertyChangedEvent(nameof(this.IsSyncEnabled));
Dean@1504
   192
            }
Dean@1504
   193
        }
Dean@1504
   194
Dean@1504
   195
        /// <summary>
Dean@384
   196
        /// Gets or sets the communication language with the identity.
Dean@384
   197
        /// </summary>
Dean@384
   198
        public string Language
Dean@384
   199
        {
Dean@384
   200
            get { return (this.internalIdentity.lang); }
Dean@1274
   201
            set
Dean@1274
   202
            {
Dean@1274
   203
                this.internalIdentity.lang = value;
Dean@1274
   204
                this.RaisePropertyChangedEvent(nameof(this.Language));
Dean@1274
   205
            }
Dean@384
   206
        }
Dean@394
   207
Dean@384
   208
        /// <summary>
Dean@384
   209
        /// Gets or sets a unique user ID for the identity.
Dean@384
   210
        /// </summary>
Dean@1348
   211
        public string UserId
Dean@384
   212
        {
markus@1347
   213
            get { return (this.internalIdentity.UserId); }
Dean@1274
   214
            set
Dean@1274
   215
            {
markus@1347
   216
                this.internalIdentity.UserId = value;
Dean@1348
   217
                this.RaisePropertyChangedEvent(nameof(this.UserId));
Dean@1274
   218
            }
Dean@384
   219
        }
Dean@384
   220
Dean@384
   221
        /// <summary>
Dean@384
   222
        /// Gets or sets the user name of the identity.
Dean@384
   223
        /// This is what the identity should be displayed as.
Dean@384
   224
        /// </summary>
Dean@1348
   225
        public string UserName
Dean@384
   226
        {
markus@1347
   227
            get { return (this.internalIdentity.UserName); }
Dean@1274
   228
            set
Dean@1274
   229
            {
markus@1347
   230
                this.internalIdentity.UserName = value;
Dean@1348
   231
                this.RaisePropertyChangedEvent(nameof(this.UserName));
Dean@1274
   232
                this.RaisePropertyChangedEvent(nameof(this.DisplayString));
Dean@1274
   233
                this.RaisePropertyChangedEvent(nameof(this.IsAddressValid));
Dean@1274
   234
            }
Dean@384
   235
        }
Dean@762
   236
Dean@760
   237
        /// <summary>
Dean@762
   238
        /// Gets or sets the force unencrypted property of the contact associated 
Dean@762
   239
        /// with this identity. The value can be null if there is no contact property.
Dean@760
   240
        /// </summary>
Dean@760
   241
        public bool? IsForceUnencrypted
Dean@760
   242
        {
Dean@760
   243
            get { return (this._IsForceUnencrypted); }
Dean@1274
   244
            set
Dean@1274
   245
            {
Dean@1274
   246
                this._IsForceUnencrypted = value;
Dean@1274
   247
                this.RaisePropertyChangedEvent(nameof(this.IsForceUnencrypted));
Dean@1274
   248
                this.RaisePropertyChangedEvent(nameof(this.IsForceUnencryptedBool));
Dean@1274
   249
            }
Dean@760
   250
        }
Dean@384
   251
Dean@394
   252
        /// <summary>
Dean@1033
   253
        /// Gets or sets whether smart address processing is enabled.
Dean@1348
   254
        /// If smart address is enabled, and the set address is empty/null, the user name is 
Dean@1033
   255
        /// considered the address if it's formatted as an address itself.
Dean@1033
   256
        /// </summary>
Dean@1033
   257
        public bool IsSmartAddressEnabled
Dean@1033
   258
        {
Dean@1033
   259
            get { return (this._IsSmartAddressEnabled); }
Dean@1274
   260
            set
Dean@1274
   261
            {
Dean@1274
   262
                this._IsSmartAddressEnabled = value;
Dean@1274
   263
                this.RaisePropertyChangedEvent(nameof(this.IsSmartAddressEnabled));
Dean@1274
   264
                this.RaisePropertyChangedEvent(nameof(this.DisplayString));
Dean@1274
   265
                this.RaisePropertyChangedEvent(nameof(this.IsAddressValid));
Dean@1274
   266
            }
Dean@1033
   267
        }
Dean@1033
   268
Dean@1033
   269
        /// <summary>
Dean@394
   270
        /// Gets the list of members in this identity if it is a group.
Dean@394
   271
        /// Note: This is not supported by the pEp engine or the COM type.
Dean@394
   272
        /// </summary>
Dean@394
   273
        public List<PEPIdentity> Members
Dean@394
   274
        {
Dean@394
   275
            get { return (this._Members); }
Dean@394
   276
        }
Dean@394
   277
Dean@1362
   278
        /// <summary>
Dean@1362
   279
        /// Gets or sets the associated rating of the identity.
Dean@1362
   280
        /// This will not be automatically calculated and must be managed externally.
Dean@1362
   281
        /// </summary>
Dean@1362
   282
        public pEpRating Rating
Dean@1362
   283
        {
Dean@1362
   284
            get { return (this._Rating); }
Dean@1362
   285
            set
Dean@1362
   286
            {
Dean@1362
   287
                this._Rating = value;
Dean@1362
   288
                this.RaisePropertyChangedEvent(nameof(this.Rating));
Dean@1362
   289
            }
Dean@1362
   290
        }
Dean@1362
   291
Dean@762
   292
        ///////////////////////////////////////////////////////////
Dean@762
   293
        // Calculated
Dean@762
   294
        ///////////////////////////////////////////////////////////
Dean@394
   295
Dean@636
   296
        /// <summary>
Dean@1348
   297
        /// Gets the string to display for this identity (based on UserName and Address).
Dean@1274
   298
        /// This internally will call .ToString().
Dean@1274
   299
        /// </summary>
Dean@1274
   300
        public string DisplayString
Dean@1274
   301
        {
Dean@1274
   302
            get { return (this.ToString()); }
Dean@1274
   303
        }
Dean@1274
   304
Dean@1274
   305
        /// <summary>
Dean@1400
   306
        /// Gets the color corresponding with the rating.
Dean@1400
   307
        /// </summary>
Dean@1400
   308
        public pEpColor Color
Dean@1400
   309
        {
Dean@1400
   310
            get { return (this._Rating.ToColor()); }
Dean@1400
   311
        }
Dean@1400
   312
Dean@1400
   313
        /// <summary>
Dean@865
   314
        /// Gets whether the identity address is valid for the pEp engine and further use.
Dean@865
   315
        /// This can only validate the basic format of the address (xxxx@xxxx.xxx).
Dean@1033
   316
        /// Note: The address used is the smart address.
Dean@1348
   317
        /// If smart address is enabled, and the set address is empty/null, the user name is 
Dean@1033
   318
        /// considered the address if it's formatted as an address itself.
Dean@865
   319
        /// </summary>
Dean@865
   320
        public bool IsAddressValid
Dean@865
   321
        {
Dean@865
   322
            get
Dean@865
   323
            {
Dean@1033
   324
                // Make sure to use the smart address
Dean@1190
   325
                return (PEPIdentity.GetIsAddressValid(this.GetSmartAddress()));
Dean@865
   326
            }
Dean@865
   327
        }
Dean@865
   328
Dean@865
   329
        /// <summary>
Dean@636
   330
        /// Gets whether this identity is empty and contains no data.
Dean@1504
   331
        /// Note: CommunicationType, Flags, Language and IsSmartAddressEnabled are ignored.
Dean@636
   332
        /// </summary>
Dean@636
   333
        public bool IsEmpty
Dean@636
   334
        {
Dean@636
   335
            get
Dean@636
   336
            {
Dean@636
   337
                bool isEmpty = true;
Dean@636
   338
Dean@1348
   339
                // Check Address
Dean@636
   340
                if (isEmpty)
Dean@636
   341
                {
Dean@1033
   342
                    // Do not use the smart address
markus@1347
   343
                    if (string.IsNullOrEmpty(this.internalIdentity.Address) == false)
Dean@636
   344
                    {
Dean@636
   345
                        isEmpty = false;
Dean@636
   346
                    }
Dean@636
   347
                }
Dean@636
   348
Dean@636
   349
                // Skip CommunicationType
Dean@636
   350
Dean@636
   351
                // Check Fingerprint
Dean@636
   352
                if (isEmpty)
Dean@636
   353
                {
Dean@636
   354
                    if (string.IsNullOrEmpty(this.internalIdentity.fpr) == false)
Dean@636
   355
                    {
Dean@636
   356
                        isEmpty = false;
Dean@636
   357
                    }
Dean@636
   358
                }
Dean@636
   359
Dean@1504
   360
                // Skip Flags
Dean@636
   361
                // Skip Language
Dean@636
   362
Dean@1348
   363
                // Check UserId
Dean@636
   364
                if (isEmpty)
Dean@636
   365
                {
markus@1347
   366
                    if (string.IsNullOrEmpty(this.internalIdentity.UserId) == false)
Dean@636
   367
                    {
Dean@636
   368
                        isEmpty = false;
Dean@636
   369
                    }
Dean@636
   370
                }
Dean@636
   371
Dean@1348
   372
                // Check UserName
Dean@636
   373
                if (isEmpty)
Dean@636
   374
                {
markus@1347
   375
                    if (string.IsNullOrEmpty(this.internalIdentity.UserName) == false)
Dean@636
   376
                    {
Dean@636
   377
                        isEmpty = false;
Dean@636
   378
                    }
Dean@636
   379
                }
Dean@636
   380
Dean@760
   381
                // Check IsForceUnencrypted
Dean@760
   382
                if (isEmpty)
Dean@760
   383
                {
Dean@760
   384
                    if (this._IsForceUnencrypted != null)
Dean@760
   385
                    {
Dean@760
   386
                        isEmpty = false;
Dean@760
   387
                    }
Dean@760
   388
                }
Dean@760
   389
Dean@1033
   390
                // Skip IsSmartAddressEnabled
Dean@1033
   391
Dean@636
   392
                // Check Members
Dean@636
   393
                if (isEmpty)
Dean@636
   394
                {
Dean@636
   395
                    for (int i = 0; i < this._Members.Count; i++)
Dean@636
   396
                    {
Dean@636
   397
                        if (this._Members[i].IsEmpty == false)
Dean@636
   398
                        {
Dean@636
   399
                            isEmpty = false;
Dean@636
   400
                            break;
Dean@636
   401
                        }
Dean@636
   402
                    }
Dean@636
   403
                }
Dean@636
   404
Dean@636
   405
                return (isEmpty);
Dean@636
   406
            }
Dean@636
   407
        }
Dean@636
   408
Dean@648
   409
        /// <summary>
Dean@762
   410
        /// Gets the true/false boolean value of the IsForceUnencrypted property 
Dean@762
   411
        /// (null is considered false).
Dean@762
   412
        /// </summary>
Dean@762
   413
        public bool IsForceUnencryptedBool
Dean@762
   414
        {
Dean@762
   415
            get
Dean@762
   416
            {
Dean@762
   417
                if ((this._IsForceUnencrypted == null) ||
Dean@762
   418
                    ((bool)this._IsForceUnencrypted == false))
Dean@762
   419
                {
Dean@762
   420
                    return (false);
Dean@762
   421
                }
Dean@762
   422
                else
Dean@762
   423
                {
Dean@762
   424
                    return (true);
Dean@762
   425
                }
Dean@762
   426
            }
Dean@762
   427
        }
Dean@762
   428
Dean@762
   429
        /// <summary>
Dean@762
   430
        /// Gets whether this identity is a group with individual members.
Dean@762
   431
        /// </summary>
Dean@762
   432
        public bool IsGroup
Dean@762
   433
        {
Dean@762
   434
            get { return (this._Members.Count > 0); }
Dean@762
   435
        }
Dean@762
   436
Dean@384
   437
        /**************************************************************
Dean@384
   438
         * 
Dean@384
   439
         * Methods
Dean@384
   440
         * 
Dean@384
   441
         *************************************************************/
Dean@384
   442
Dean@384
   443
        /// <summary>
Dean@1274
   444
        /// Raises the property changed event, if possible, with the given arguments.
Dean@1274
   445
        /// </summary>
Dean@1274
   446
        /// <param name="propertyName">The name of the property that changed.</param>
Dean@1274
   447
        private void RaisePropertyChangedEvent(string propertyName)
Dean@1274
   448
        {
Dean@1274
   449
            this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
Dean@1274
   450
            return;
Dean@1274
   451
        }
Dean@1274
   452
Dean@1274
   453
        /// <summary>
Dean@384
   454
        /// Returns this pEp identity as a pEp engine identity.
Dean@1033
   455
        /// Copied data is used in the COM type.
Dean@1033
   456
        /// Note: This will not include any members of a group, 
Dean@1033
   457
        /// also the address used is the smart address.
Dean@384
   458
        /// </summary>
Dean@384
   459
        /// <returns>A pEp engine identity.</returns>
markus@1337
   460
        public pEpIdentity ToCOMType()
Dean@384
   461
        {
markus@1337
   462
            pEpIdentity newIdent = new pEpIdentity();
Dean@1033
   463
markus@1347
   464
            newIdent.Address = this.GetSmartAddress();
markus@1347
   465
            newIdent.CommType = this.internalIdentity.CommType;
Dean@1033
   466
            newIdent.fpr = this.internalIdentity.fpr;
Dean@1504
   467
            newIdent.Flags = this.internalIdentity.Flags;
Dean@1033
   468
            newIdent.lang = this.internalIdentity.lang;
markus@1347
   469
            newIdent.UserId = this.internalIdentity.UserId;
markus@1347
   470
            newIdent.UserName = this.internalIdentity.UserName;
Dean@1033
   471
Dean@1033
   472
            return (newIdent);
Dean@384
   473
        }
Dean@384
   474
Dean@384
   475
        /// <summary>
Dean@1238
   476
        /// Serves as a hash function for a particular type.
Dean@1238
   477
        /// </summary>
Dean@1238
   478
        /// <returns>A hash code for the current object.</returns>
Dean@1238
   479
        public override int GetHashCode()
Dean@1238
   480
        {
Dean@1238
   481
            return base.GetHashCode();
Dean@1238
   482
        }
Dean@1238
   483
Dean@1238
   484
        /// <summary>
Dean@1238
   485
        /// Indicates whether the current object is equal to another object of the same type.
Dean@1238
   486
        /// </summary>
Dean@1238
   487
        /// <param name="obj">The object to check equality with.</param>
Dean@1238
   488
        /// <returns>True if both objects are considered equal, otherwise false.</returns>
Dean@1238
   489
        public override bool Equals(object obj)
Dean@1238
   490
        {
Dean@1238
   491
            if ((obj == null) ||
Dean@1238
   492
                !(obj is PEPIdentity))
Dean@1238
   493
            {
Dean@1238
   494
                return (false);
Dean@1238
   495
            }
Dean@1238
   496
Dean@1238
   497
            return (this.Equals((PEPIdentity)obj));
Dean@1238
   498
        }
Dean@1238
   499
Dean@1238
   500
        /// <summary>
Dean@1238
   501
        /// Indicates whether the current object is equal to another object of the same type.
Dean@1238
   502
        /// </summary>
Dean@1238
   503
        /// <param name="obj">The object to check equality with.</param>
Dean@1238
   504
        /// <returns>True if both objects are considered equal, otherwise false.</returns>
Dean@1238
   505
        public bool Equals(PEPIdentity obj)
Dean@1238
   506
        {
Dean@1238
   507
            if (obj == null)
Dean@1238
   508
            {
Dean@1238
   509
                return (false);
Dean@1238
   510
            }
Dean@1238
   511
Dean@1238
   512
            if (Comparisons.Equals(this.Address, obj.Address) &&
Dean@1238
   513
                Comparisons.Equals(this.CommunicationType, obj.CommunicationType) &&
Dean@1238
   514
                Comparisons.Equals(this.Fingerprint, obj.Fingerprint) &&
Dean@1238
   515
                Comparisons.Equals(this.Language, obj.Language) &&
Dean@1348
   516
                Comparisons.Equals(this.UserId, obj.UserId) &&
Dean@1348
   517
                Comparisons.Equals(this.UserName, obj.UserName) &&
Dean@1238
   518
                Comparisons.Equals(this.IsForceUnencrypted, obj.IsForceUnencrypted) &&
Dean@1238
   519
                Comparisons.Equals(this.IsSmartAddressEnabled, obj.IsSmartAddressEnabled) &&
Dean@1362
   520
                Comparisons.Equals(this.Members, obj.Members) &&
Dean@1362
   521
                Comparisons.Equals(this.Rating, obj.Rating))
Dean@1238
   522
            {
Dean@1238
   523
                return (true);
Dean@1238
   524
            }
Dean@1238
   525
Dean@1238
   526
            return (false);
Dean@1238
   527
        }
Dean@1238
   528
Dean@1238
   529
        /// <summary>
Thomas@1444
   530
        /// Gets a deep copy of the object and all its data.
Dean@384
   531
        /// </summary>
Dean@384
   532
        /// <returns>The deep copy of the object.</returns>
Dean@384
   533
        public PEPIdentity Copy()
Dean@384
   534
        {
Dean@384
   535
            PEPIdentity copy = new PEPIdentity();
Dean@384
   536
markus@1347
   537
            copy.Address = (this.internalIdentity.Address == null ? null : string.Copy(this.internalIdentity.Address));
markus@1347
   538
            copy.CommunicationType = this.internalIdentity.CommType;
Dean@1291
   539
            copy.Fingerprint = (this.internalIdentity.fpr == null ? null : string.Copy(this.internalIdentity.fpr));
Dean@1504
   540
            copy.IsInDeviceGroup = this.internalIdentity.GetIsInDeviceGroup();
Dean@1504
   541
            copy.IsList = this.internalIdentity.GetIsList();
Dean@1504
   542
            copy.IsSyncEnabled = this.internalIdentity.GetIsSyncEnabled();
Dean@1291
   543
            copy.Language = (this.internalIdentity.lang == null ? null : string.Copy(this.internalIdentity.lang));
Dean@1348
   544
            copy.UserId = (this.internalIdentity.UserId == null ? null : string.Copy(this.internalIdentity.UserId));
Dean@1348
   545
            copy.UserName = (this.internalIdentity.UserName == null ? null : string.Copy(this.internalIdentity.UserName));
Dean@384
   546
Dean@760
   547
            // IsForceUnencrypted
Dean@760
   548
            if (this._IsForceUnencrypted != null)
Dean@760
   549
            {
Dean@760
   550
                copy.IsForceUnencrypted = (bool)this.IsForceUnencrypted;
Dean@760
   551
            }
Dean@760
   552
            else
Dean@760
   553
            {
Dean@760
   554
                copy.IsForceUnencrypted = null;
Dean@760
   555
            }
Dean@760
   556
Dean@1033
   557
            copy.IsSmartAddressEnabled = this.IsSmartAddressEnabled;
Dean@1033
   558
Dean@394
   559
            // Members
Dean@394
   560
            copy.Members.Clear();
Dean@394
   561
            for (int i = 0; i < this._Members.Count; i++)
Dean@394
   562
            {
Dean@394
   563
                copy.Members.Add(this._Members[i].Copy());
Dean@394
   564
            }
Dean@394
   565
Dean@1362
   566
            copy.Rating = this._Rating;
Dean@1362
   567
Dean@384
   568
            return (copy);
Dean@384
   569
        }
Dean@384
   570
Dean@384
   571
        /// <summary>
Dean@1496
   572
        /// Indicates whether the current PEPIdentity is equal to another PEPIdentity by address only (case insensitive).
Dean@1033
   573
        /// Note: The address used is the smart address.
Dean@1155
   574
        /// Note: If either (or both) address is null or empty, they are considered NOT equal.
Dean@384
   575
        /// </summary>
Dean@1496
   576
        /// <param name="obj">The PEPIdentity to compare against.</param>
Dean@1134
   577
        /// <returns>True if the given address and this object's address are neither null nor empty and considered equal, otherwise false.</returns>
Dean@527
   578
        public bool EqualsByAddress(PEPIdentity obj)
Dean@384
   579
        {
Dean@384
   580
            bool areEqual = false;
Dean@1033
   581
            string addr = this.GetSmartAddress();
Dean@384
   582
Dean@384
   583
            if ((obj != null) &&
Dean@1134
   584
                (string.IsNullOrEmpty(obj.Address) == false) &&
Dean@1134
   585
                (string.IsNullOrEmpty(addr) == false))
Dean@384
   586
            {
Dean@1155
   587
                areEqual = string.Equals(addr.Trim(), obj.Address.Trim(), StringComparison.OrdinalIgnoreCase);
Dean@384
   588
            }
Dean@384
   589
Dean@384
   590
            return (areEqual);
Dean@384
   591
        }
Dean@384
   592
Dean@394
   593
        /// <summary>
Dean@1496
   594
        /// Indicates whether the current PEPIdentity is equal to an address only (case insensitive).
Thomas@1131
   595
        /// Note: The address used is the smart address.
Dean@1155
   596
        /// Note: If either (or both) address is null or empty, they are considered NOT equal.
Thomas@1131
   597
        /// </summary>
Thomas@1131
   598
        /// <param name="address">The address to compare against.</param>
Thomas@1131
   599
        /// <returns>True if the given address and this object's address are neither null nor empty and considered equal, otherwise false.</returns>
Thomas@1131
   600
        public bool EqualsByAddress(string address)
Thomas@1131
   601
        {
Thomas@1131
   602
            bool areEqual = false;
Thomas@1131
   603
            string addr = this.GetSmartAddress();
Thomas@1131
   604
Dean@1134
   605
            if ((string.IsNullOrEmpty(address) == false) &&
Dean@1134
   606
                (string.IsNullOrEmpty(addr) == false))
Thomas@1131
   607
            {
Dean@1155
   608
                areEqual = string.Equals(addr.Trim(), address.Trim(), StringComparison.OrdinalIgnoreCase);
Thomas@1131
   609
            }
Thomas@1131
   610
Thomas@1131
   611
            return (areEqual);
Thomas@1131
   612
        }
Thomas@1131
   613
Thomas@1131
   614
        /// <summary>
Dean@394
   615
        /// Recursivley converts the given identity into a 'flat' list of any members.
Thomas@1444
   616
        /// This will remove groups (hierarchy) and convert a group into its members.
Dean@394
   617
        /// </summary>
Dean@394
   618
        /// <param name="identity">The identity to get the flat list for.</param>
Dean@394
   619
        /// <returns>The flat list of pEp identities in the identity.</returns>
Dean@394
   620
        public List<PEPIdentity> ToFlatList()
Dean@394
   621
        {
Dean@394
   622
            List<PEPIdentity> result = new List<PEPIdentity>();
Dean@394
   623
            this.RecToFlatList(this, result);
Dean@394
   624
            return (result);
Dean@394
   625
        }
Dean@394
   626
Dean@394
   627
        /// <summary>
Dean@394
   628
        /// Recursively adds members of any group in the given identity to the list.
Dean@394
   629
        /// </summary>
Dean@394
   630
        /// <param name="identity">The identity to process.</param>
Dean@394
   631
        /// <param name="list">The list to add identities to.</param>
Dean@394
   632
        private void RecToFlatList(PEPIdentity identity,
Dean@394
   633
                                   List<PEPIdentity> list)
Dean@394
   634
        {
Dean@394
   635
            List<PEPIdentity> memberList;
Dean@394
   636
Dean@394
   637
            if (identity.IsGroup)
Dean@394
   638
            {
Dean@394
   639
                for (int i = 0; i < identity.Members.Count; i++)
Dean@394
   640
                {
Dean@394
   641
                    memberList = new List<PEPIdentity>();
Dean@394
   642
                    this.RecToFlatList(identity.Members[i], memberList);
Dean@394
   643
Dean@394
   644
                    for (int j = 0; j < memberList.Count; j++)
Dean@394
   645
                    {
Dean@394
   646
                        list.Add(memberList[j]);
Dean@394
   647
                    }
Dean@394
   648
                }
Dean@394
   649
            }
Dean@394
   650
            else
Dean@394
   651
            {
Dean@394
   652
                list.Add(identity.Copy());
Dean@394
   653
            }
Dean@394
   654
Dean@394
   655
            return;
Dean@394
   656
        }
Dean@394
   657
Dean@599
   658
        /// <summary>
Dean@1033
   659
        /// Gets the calculated smart address for this identity.
Dean@1348
   660
        /// If smart address is enabled, and the set address is empty/null, the user name may be returned as the address
Dean@1033
   661
        /// if it's formatted as an address.
Dean@1033
   662
        /// </summary>
Dean@1033
   663
        /// <returns>The calculated 'smart' adress for this identity.</returns>
Dean@1033
   664
        private string GetSmartAddress()
Dean@1033
   665
        {
markus@1347
   666
            string addr = this.internalIdentity.Address;
Dean@1033
   667
Dean@1033
   668
            // If smart address processing is enabled, and the internal address is null/empty,
Dean@1348
   669
            // check if the user name is valid and return it as the address.
Dean@1033
   670
            if ((this._IsSmartAddressEnabled) &&
markus@1347
   671
                (string.IsNullOrWhiteSpace(this.internalIdentity.Address)))
Dean@1033
   672
            {
markus@1347
   673
                if (PEPIdentity.GetIsAddressValid(this.internalIdentity.UserName))
Dean@1033
   674
                {
markus@1347
   675
                    addr = this.internalIdentity.UserName;
Dean@1033
   676
                }
Dean@1033
   677
            }
Dean@1033
   678
Dean@1033
   679
            return (addr);
Dean@1033
   680
        }
Dean@1033
   681
Dean@1033
   682
        /// <summary>
Dean@599
   683
        /// Returns a string that represents this identity.
Dean@1033
   684
        /// Note: The address used is the smart address.
Dean@599
   685
        /// </summary>
Dean@599
   686
        /// <returns>The string representing the identity which can be empty.</returns>
Dean@599
   687
        public override string ToString()
Dean@599
   688
        {
Dean@599
   689
            string result = "";
markus@1347
   690
            string usrname = this.internalIdentity.UserName;
Dean@1033
   691
            string addr = this.GetSmartAddress();
Dean@633
   692
Dean@1033
   693
            if ((string.IsNullOrWhiteSpace(usrname) == true) &&
Dean@1033
   694
                (string.IsNullOrWhiteSpace(addr) == true))
Dean@599
   695
            {
Dean@1033
   696
                // Do nothing, return empty
Dean@599
   697
            }
Dean@1033
   698
            else if ((string.IsNullOrWhiteSpace(usrname) == true) &&
Dean@1033
   699
                     (string.IsNullOrWhiteSpace(addr) == false))
Dean@599
   700
            {
Dean@1033
   701
                result = addr.Trim();
Dean@1033
   702
            }
Dean@1033
   703
            else if ((string.IsNullOrWhiteSpace(usrname) == false) &&
Dean@1033
   704
                     (string.IsNullOrWhiteSpace(addr) == true))
Dean@1033
   705
            {
Dean@1033
   706
                result = usrname.Trim();
Dean@1033
   707
            }
Dean@1033
   708
            else if ((string.IsNullOrWhiteSpace(usrname) == false) &&
Dean@1033
   709
                     (string.IsNullOrWhiteSpace(addr) == false))
Dean@1033
   710
            {
Dean@1033
   711
                if (usrname.Trim() == addr.Trim())
Dean@1033
   712
                {
Dean@1033
   713
                    result = usrname.Trim();
Dean@1033
   714
                }
Dean@1033
   715
                else
Dean@1033
   716
                {
Dean@1033
   717
                    result = usrname.Trim() + " <" + addr.Trim() + ">";
Dean@1033
   718
                }
Dean@599
   719
            }
Dean@599
   720
Dean@599
   721
            return (result);
Dean@599
   722
        }
Dean@599
   723
Dean@789
   724
        /// <summary>
Dean@789
   725
        /// Returns a string that represents this identity specifically for display.
Dean@1348
   726
        /// This will use the user name if it exists, otherwise address.
Dean@789
   727
        /// </summary>
Dean@789
   728
        /// <returns>The display string representing the identity which can be empty.</returns>
Dean@789
   729
        public string ToDisplayString()
Dean@789
   730
        {
Dean@789
   731
            string result = "";
Dean@789
   732
markus@1347
   733
            if (string.IsNullOrWhiteSpace(this.internalIdentity.UserName) == false)
Dean@789
   734
            {
markus@1347
   735
                result = this.internalIdentity.UserName.Trim();
Dean@789
   736
            }
Dean@1348
   737
            // Do not use the smart address (no need since user name is tried first)
markus@1347
   738
            else if (string.IsNullOrWhiteSpace(this.internalIdentity.Address) == false)
Dean@789
   739
            {
markus@1347
   740
                result = this.internalIdentity.Address.Trim();
Dean@789
   741
            }
Dean@789
   742
Dean@789
   743
            return (result);
Dean@789
   744
        }
Dean@789
   745
Dean@384
   746
        /**************************************************************
Dean@384
   747
         * 
Dean@384
   748
         * Static Methods
Dean@384
   749
         * 
Dean@384
   750
         *************************************************************/
Dean@384
   751
Dean@384
   752
        /// <summary>
Dean@1250
   753
        /// Parses the given string as a new PEPIdentity. This will never return null.
Dean@1190
   754
        /// The string should be of the format 'user name &lt;email@address.com&gt;'
Dean@1190
   755
        /// If the string does not have both &lt; and &gt; it will be read as an address if it is a valid address, 
Dean@1348
   756
        /// otherwise a user name.
Dean@1190
   757
        /// </summary>
Dean@1190
   758
        /// <param name="str">The string to parse as a PEPIdentity.</param>
Dean@1190
   759
        /// <returns>The string parsed as a PEPIdentity, otherwise null if failure.</returns>
Dean@1190
   760
        public static PEPIdentity Parse(string str)
Dean@1190
   761
        {
Dean@1190
   762
            int addressStartSymbol;
Dean@1190
   763
            int addressEndSymbol;
Dean@1190
   764
            string workingStr;
Dean@1190
   765
            string userName;
Dean@1190
   766
            string address;
Dean@1190
   767
            string[] temp;
Dean@1250
   768
            PEPIdentity result = new PEPIdentity();
Dean@1190
   769
Dean@1190
   770
            if (string.IsNullOrWhiteSpace(str) == false)
Dean@1190
   771
            {
Dean@1190
   772
                workingStr = str.Trim();
Dean@1190
   773
                addressStartSymbol = workingStr.IndexOf("<");
Dean@1190
   774
                addressEndSymbol = workingStr.IndexOf(">");
Dean@1190
   775
Dean@1190
   776
                if ((addressStartSymbol < 0) &&
Dean@1190
   777
                    (addressEndSymbol < 0))
Dean@1190
   778
                {
Dean@1190
   779
                    if (PEPIdentity.GetIsAddressValid(workingStr))
Dean@1190
   780
                    {
Dean@1190
   781
                        // Only address
Dean@1190
   782
                        result = new PEPIdentity();
Dean@1190
   783
                        result.Address = workingStr;
Dean@1190
   784
                    }
Dean@1190
   785
                    else
Dean@1190
   786
                    {
Dean@1190
   787
                        // Only user name
Dean@1190
   788
                        result = new PEPIdentity();
Dean@1348
   789
                        result.UserName = workingStr;
Dean@1190
   790
                    }
Dean@1190
   791
                }
Dean@1190
   792
                else if ((addressStartSymbol >= 0) &&
Dean@1190
   793
                         (addressEndSymbol >= 0) &&
Dean@1190
   794
                         (addressEndSymbol > addressStartSymbol) &&
Dean@1190
   795
                         (workingStr.LastIndexOf("<") == addressStartSymbol) &&
Dean@1190
   796
                         (workingStr.LastIndexOf(">") == addressEndSymbol))
Dean@1190
   797
                {
Dean@1190
   798
                    temp = workingStr.Split('<');
Dean@1190
   799
Dean@1190
   800
                    if (temp.Length == 2)
Dean@1190
   801
                    {
Dean@1190
   802
                        userName = temp[0].Trim();
Dean@1190
   803
                        address = temp[1].Replace(">", "").Trim();
Dean@1190
   804
Dean@1190
   805
                        // Require both the user name and address to exist
Dean@1190
   806
                        if ((string.IsNullOrWhiteSpace(userName) == false) &&
Dean@1190
   807
                            (PEPIdentity.GetIsAddressValid(address)))
Dean@1190
   808
                        {
Dean@1190
   809
                            result = new PEPIdentity();
Dean@1348
   810
                            result.UserName = userName;
Dean@1190
   811
                            result.Address = address;
Dean@1190
   812
                        }
Dean@1190
   813
                    }
Dean@1190
   814
                }
Dean@1190
   815
            }
Dean@1190
   816
Dean@1190
   817
            return (result);
Dean@1190
   818
        }
Dean@1190
   819
Dean@1190
   820
        /// <summary>
Dean@1190
   821
        /// Gets whether the given address string is considered valid based on its format.
Dean@1190
   822
        /// This can only validate the basic format of the address (xxxx@xxxx.xxx).
Dean@1190
   823
        /// </summary>
Dean@1190
   824
        /// <param name="address">The address string to determine if it's valid.</param>
Dean@1190
   825
        /// <returns>True if the address string's format is valid, otherwise false.</returns>
Dean@1190
   826
        public static bool GetIsAddressValid(string address)
Dean@1190
   827
        {
Dean@1190
   828
            if ((string.IsNullOrWhiteSpace(address) == false) &&
Dean@1381
   829
                (address.Contains("@")))
Dean@1190
   830
            {
Dean@1381
   831
                return (true);
Dean@1190
   832
            }
Dean@1190
   833
Dean@1381
   834
            return (false);
Dean@1190
   835
        }
Dean@1190
   836
Dean@1190
   837
        /// <summary>
Dean@1198
   838
        /// Gets whether the given address represents an own personal identity (myself).
Dean@1198
   839
        /// This is done by comparing against the current session's account list.
Dean@1198
   840
        /// If a registered account's SMTP address, or current user address, matches the given address (case insensitive), it is a match.
Dean@1198
   841
        /// This means it should work for both Exchange formatted and normal address strings.
Dean@713
   842
        /// </summary>
Dean@1198
   843
        /// <param name="address">The email address to check if it is an own identity.</param>
Dean@1198
   844
        /// <returns>True if the given address represents an own identity, otherwise false.</returns>
Dean@910
   845
        public static bool GetIsOwnIdentity(string address)
Dean@713
   846
        {
Dean@1198
   847
            bool isMyself;
Dean@1198
   848
            Outlook.Account account;
Dean@713
   849
Dean@1198
   850
            account = PEPIdentity.GetOwnAccount(address);
Dean@1198
   851
            isMyself = (account != null ? true : false);
Dean@1196
   852
Dean@1198
   853
            if (account != null)
Dean@713
   854
            {
vb@1507
   855
                // Marshal.ReleaseComObject(account);
Dean@1198
   856
                account = null;
Dean@713
   857
            }
Dean@713
   858
Dean@713
   859
            return (isMyself);
Dean@713
   860
        }
Dean@713
   861
Dean@713
   862
        /// <summary>
Dean@1455
   863
        /// Gets an own identity using the given email address (can handle exchange encoded addresses).
Dean@635
   864
        /// The account for the email address must already exist in Outlook.
Dean@910
   865
        /// Warning: The result can be null.
Dean@384
   866
        /// </summary>
Dean@1455
   867
        /// <param name="address">The email address to get the own identity from.</param>
Dean@910
   868
        /// <param name="ownIdentity">The output own identity (may be null).</param>
Dean@1455
   869
        /// <returns>The own identity or null.</returns>
Dean@910
   870
        public static Globals.ReturnStatus GetOwnIdentity(string address,
Dean@910
   871
                                                          out PEPIdentity ownIdentity)
Dean@384
   872
        {
markus@1337
   873
            pEpIdentity ident;
Dean@910
   874
            PEPIdentity ownBaseIdentity = null;
Dean@910
   875
            PEPIdentity own = null;
Dean@633
   876
            Outlook.Account account = null;
Dean@1455
   877
            Globals.ReturnStatus sts;
Dean@910
   878
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@384
   879
Dean@633
   880
            try
Dean@384
   881
            {
Dean@1205
   882
                account = PEPIdentity.GetOwnAccount(address);
Dean@1205
   883
Dean@1455
   884
                // Get the identity of the account, ignore any errors
Dean@1455
   885
                sts = PEPIdentity.GetOwnIdentity(account, out ownBaseIdentity);
Dean@1205
   886
Dean@1205
   887
                // Update the identity in the pEp engine (and get fingerprint)
Dean@1205
   888
                if (ownBaseIdentity != null)
Dean@1205
   889
                {
Dean@1205
   890
                    try
Dean@1205
   891
                    {
markus@1337
   892
                        ident = ThisAddIn.PEPEngine.Myself(ownBaseIdentity.ToCOMType());
Dean@1205
   893
                        own = new PEPIdentity(ident);
Dean@1205
   894
                        status = Globals.ReturnStatus.Success;
Dean@1205
   895
                    }
Dean@1205
   896
                    catch
Dean@1205
   897
                    {
Dean@1205
   898
                        own = null;
Dean@1205
   899
                        status = Globals.ReturnStatus.Failure;
Dean@633
   900
                    }
Dean@384
   901
                }
Dean@384
   902
            }
Dean@910
   903
            catch (Exception ex)
Dean@910
   904
            {
Dean@910
   905
                status = Globals.ReturnStatus.Failure;
Dean@1249
   906
                Log.Error("GetOwnIdentity: Failure occured, " + ex.ToString());
Dean@910
   907
            }
Dean@633
   908
            finally
Dean@384
   909
            {
Dean@633
   910
                if (account != null)
Dean@384
   911
                {
vb@1507
   912
                    // Marshal.ReleaseComObject(account);
Dean@633
   913
                    account = null;
Dean@633
   914
                }
Dean@384
   915
            }
Dean@384
   916
Dean@910
   917
            ownIdentity = own;
Dean@910
   918
            return (status);
Dean@384
   919
        }
Dean@384
   920
Dean@384
   921
        /// <summary>
Dean@1198
   922
        /// Gets the Outlook account in this session that corresponds with the given address.
Dean@1198
   923
        /// If a registered account's SMTP address, or current user address, matches the given address (case insensitive), it is a match.
Dean@1198
   924
        /// This means it should work for both Exchange formatted and normal address strings.
Dean@1198
   925
        /// Warning: If multiple accounts have the same address this will only return the first one.
Dean@1198
   926
        /// </summary>
Dean@1198
   927
        /// <param name="address">The email address to find the account for.</param>
Dean@1198
   928
        /// <returns>The own Outlook Acccount associated with given address, otherwise null.
Dean@1198
   929
        /// The caller has ownership of the returned account.</returns>
Dean@1198
   930
        public static Outlook.Account GetOwnAccount(string address)
Dean@1198
   931
        {
Dean@1198
   932
            bool accountFound = false;
Dean@1198
   933
            string workingAddress;
Dean@1198
   934
            string accountAddress;
Dean@1198
   935
            string currUserAddress;
Dean@1198
   936
            Outlook.Account account = null;
Dean@1198
   937
            Outlook.Accounts accounts = null;
Dean@1198
   938
            Outlook.NameSpace ns = null;
Dean@1198
   939
            Outlook.Recipient currUser = null;
Dean@1198
   940
Dean@1198
   941
            /* Note: For exchange accounts the given address may not be an actual address unless the caller correctly 
Dean@1198
   942
             * gets the exchange user then the exchange user's address.
Dean@1198
   943
             * However, this function can handle both situations by simply checking against both the account smtp address
Dean@1198
   944
             * and the account's current user address.
Dean@1198
   945
             * If an exchange encoded address is given, it should match against the current user which also will have an
Dean@1198
   946
             * exchange encoded address. Otherwise, it should match against the account smpt address.
Dean@1198
   947
             */
Dean@1198
   948
Dean@1198
   949
            try
Dean@1198
   950
            {
Dean@1198
   951
                if (string.IsNullOrWhiteSpace(address) == false)
Dean@1198
   952
                {
Dean@1198
   953
                    ns = Globals.ThisAddIn.Application.Session;
Dean@1198
   954
                    accounts = ns.Accounts;
Dean@1198
   955
                    workingAddress = address.Trim();
Dean@1198
   956
Dean@1198
   957
                    // Look in existing accounts
Dean@1198
   958
                    for (int i = 1; i <= accounts.Count; i++)
Dean@1198
   959
                    {
Dean@1198
   960
                        account = accounts[i];
Dean@1198
   961
                        currUser = account.CurrentUser;
Dean@1198
   962
                        accountAddress = (account.SmtpAddress != null ? account.SmtpAddress.Trim() : "");
Dean@1198
   963
                        currUserAddress = (currUser.Address != null ? currUser.Address.Trim() : "");
Dean@1198
   964
Dean@1198
   965
                        // Match by current user or account account
Dean@1198
   966
                        if ((string.IsNullOrEmpty(accountAddress) == false) &&
Dean@1198
   967
                            (string.IsNullOrEmpty(currUserAddress) == false) &&
Dean@1198
   968
                            ((string.Equals(workingAddress, currUserAddress, StringComparison.OrdinalIgnoreCase)) ||
Dean@1198
   969
                             (string.Equals(workingAddress, accountAddress, StringComparison.OrdinalIgnoreCase))))
Dean@1198
   970
                        {
Dean@1198
   971
                            accountFound = true;
Dean@1198
   972
                        }
Dean@1198
   973
Dean@1198
   974
                        if (currUser != null)
Dean@1198
   975
                        {
vb@1507
   976
                            // Marshal.ReleaseComObject(currUser);
Dean@1198
   977
                            currUser = null;
Dean@1198
   978
                        }
Dean@1198
   979
Dean@1198
   980
                        // Do not release the account if it was a match
Dean@1198
   981
                        if ((account != null) &&
Dean@1198
   982
                            (accountFound == false))
Dean@1198
   983
                        {
vb@1507
   984
                            // Marshal.ReleaseComObject(account);
Dean@1198
   985
                            account = null;
Dean@1198
   986
                        }
Dean@1198
   987
Dean@1198
   988
                        if (accountFound)
Dean@1198
   989
                        {
Dean@1198
   990
                            break;
Dean@1198
   991
                        }
Dean@1198
   992
                    }
Dean@1198
   993
                }
Dean@1198
   994
            }
Dean@1198
   995
            catch (Exception ex)
Dean@1198
   996
            {
Dean@1249
   997
                Log.Error("GetOwnAccount: Failure occured, " + ex.ToString());
Dean@1198
   998
            }
Dean@1198
   999
            finally
Dean@1198
  1000
            {
Dean@1198
  1001
                // Do not release the account if it was a match
Dean@1198
  1002
                if ((account != null) &&
Dean@1198
  1003
                    (accountFound == false))
Dean@1198
  1004
                {
vb@1507
  1005
                    // Marshal.ReleaseComObject(account);
Dean@1198
  1006
                    account = null;
Dean@1198
  1007
                }
Dean@1198
  1008
Dean@1198
  1009
                if (accounts != null)
Dean@1198
  1010
                {
vb@1507
  1011
                    // Marshal.ReleaseComObject(accounts);
Dean@1198
  1012
                    accounts = null;
Dean@1198
  1013
                }
Dean@1198
  1014
Dean@1198
  1015
                if (ns != null)
Dean@1198
  1016
                {
vb@1507
  1017
                    // Marshal.ReleaseComObject(ns);
Dean@1198
  1018
                    ns = null;
Dean@1198
  1019
                }
Dean@1198
  1020
Dean@1198
  1021
                if (currUser != null)
Dean@1198
  1022
                {
vb@1507
  1023
                    // Marshal.ReleaseComObject(currUser);
Dean@1198
  1024
                    currUser = null;
Dean@1198
  1025
                }
Dean@1198
  1026
            }
Dean@1198
  1027
Dean@1198
  1028
            return (account);
Dean@1198
  1029
        }
Dean@1198
  1030
Dean@1198
  1031
        /// <summary>
Dean@384
  1032
        /// Gets the personal identity using the given cryptable mail item.
Dean@729
  1033
        /// An account for the personal identity does not need to exist in Outlook.
Dean@910
  1034
        /// Warning: The result can be null.
Dean@384
  1035
        /// </summary>
Dean@633
  1036
        /// <param name="omi">The mail item to get the personal identity from.</param>
Dean@910
  1037
        /// <param name="ownIdentity">The output own identity (may be null).</param>
Dean@910
  1038
        /// <returns>The status of the method.</returns>
Dean@910
  1039
        public static Globals.ReturnStatus GetOwnIdentity(Outlook.MailItem omi,
Dean@910
  1040
                                                          out PEPIdentity ownIdentity)
Dean@384
  1041
        {
Dean@384
  1042
            string entryID;
Dean@384
  1043
            string address = null;
Dean@1348
  1044
            string userName = null;
markus@1337
  1045
            pEpIdentity ident;
Dean@910
  1046
            PEPIdentity own = null;
Dean@910
  1047
            PEPIdentity from = null;
Dean@633
  1048
            Outlook.Account account = null;
Dean@633
  1049
            Outlook.Accounts accounts = null;
Dean@633
  1050
            Outlook.NameSpace ns = null;
Dean@633
  1051
            Outlook.Recipient currUser = null;
Dean@910
  1052
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@910
  1053
            Globals.ReturnStatus sts;
Dean@384
  1054
Dean@633
  1055
            try
Dean@384
  1056
            {
Dean@1303
  1057
                if (omi.GetIsIncoming())
Dean@633
  1058
                {
Dean@633
  1059
                    entryID = omi.ReceivedByEntryID;
Dean@633
  1060
                    ns = Globals.ThisAddIn.Application.Session;
Dean@633
  1061
                    accounts = ns.Accounts;
Dean@1455
  1062
Dean@1455
  1063
                    // Attempt to get address by entry ID
Dean@633
  1064
                    for (int i = 1; i <= accounts.Count; i++)
Dean@633
  1065
                    {
Dean@633
  1066
                        account = accounts[i];
Dean@633
  1067
                        currUser = account.CurrentUser;
Dean@384
  1068
Dean@633
  1069
                        if (currUser != null)
Dean@633
  1070
                        {
Dean@633
  1071
                            if (currUser.EntryID == entryID)
Dean@633
  1072
                            {
Dean@633
  1073
                                address = account.SmtpAddress;
Dean@633
  1074
                                break;
Dean@633
  1075
                            }
Dean@633
  1076
vb@1507
  1077
                            // Marshal.ReleaseComObject(currUser);
Dean@633
  1078
                            currUser = null;
Dean@633
  1079
                        }
Dean@633
  1080
vb@1507
  1081
                        // Marshal.ReleaseComObject(account);
Dean@633
  1082
                        account = null;
Dean@633
  1083
                    }
Dean@633
  1084
Dean@729
  1085
                    // Attempt to get the address from the MAPI property
Dean@633
  1086
                    if (string.IsNullOrWhiteSpace(address))
Dean@633
  1087
                    {
Dean@1350
  1088
                        address = (string)MapiHelper.GetProperty(omi, MapiProperty.PidTagReceivedByEmailAddress);
vb@1512
  1089
                        if (address[0] == '/')
vb@1512
  1090
                            address = null;
Dean@633
  1091
                    }
Dean@633
  1092
vb@1511
  1093
                    // Attempt to find the account, test by containing folder
vb@1511
  1094
                    if (string.IsNullOrWhiteSpace(address))
vb@1511
  1095
                    {
vb@1511
  1096
                        Outlook.Folder parent = omi.Parent;
vb@1511
  1097
                        Outlook.Store store = parent.Store;
vb@1511
  1098
                        foreach (Outlook.Account a in accounts)
vb@1511
  1099
                        {
vb@1511
  1100
                            if (store.StoreID == a.DeliveryStore.StoreID)
vb@1511
  1101
                            {
vb@1512
  1102
                                address = a.SmtpAddress;
vb@1511
  1103
                                break;
vb@1511
  1104
                            }
vb@1511
  1105
                        }
vb@1516
  1106
                        // Marshal.ReleaseComObject(parent);
vb@1511
  1107
                    }
vb@1511
  1108
vb@1511
  1109
                    // nothing worked, use default
vb@1511
  1110
                    if (string.IsNullOrWhiteSpace(address))
vb@1511
  1111
                    {
vb@1511
  1112
                        address = accounts[1].SmtpAddress;
vb@1511
  1113
                    }
vb@1511
  1114
Dean@910
  1115
                    sts = PEPIdentity.GetOwnIdentity(address, out own);
Dean@910
  1116
                    status = sts; // Can return the just calculated value, therefore set status
Dean@1012
  1117
Dean@729
  1118
                    /* Try using the mail item received-by user property information directly.
Dean@729
  1119
                     * Only incoming messages can do this, outgoing 'myself' identites must exist after GetMyIdentity(address).
Dean@729
  1120
                     */
Dean@910
  1121
                    if ((own == null) ||
Dean@910
  1122
                        (sts != Globals.ReturnStatus.Success))
Dean@729
  1123
                    {
Dean@1350
  1124
                        address = (string)omi.GetUserProperty(MapiProperty.PidTagReceivedByEmailAddress.DaslName);
Dean@1350
  1125
                        userName = (string)omi.GetUserProperty(MapiProperty.PidTagReceivedByName.DaslName);
Dean@729
  1126
Dean@729
  1127
                        if (string.IsNullOrEmpty(address) == false)
Dean@729
  1128
                        {
Dean@910
  1129
                            own = new PEPIdentity();
Dean@910
  1130
                            own.Address = address;
Dean@1348
  1131
                            own.UserName = userName;
Dean@1348
  1132
                            own.UserId = Globals.ThisAddIn.GetUserId(own.Address, null); // Not using 'myself ID'
Dean@729
  1133
Dean@729
  1134
                            // Update the identity in the pEp engine (and get fingerprint)
Dean@729
  1135
                            try
Dean@729
  1136
                            {
markus@1337
  1137
                                ident = ThisAddIn.PEPEngine.Myself(own.ToCOMType());
Dean@910
  1138
                                own = new PEPIdentity(ident);
Dean@910
  1139
                                status = Globals.ReturnStatus.Success;
Dean@729
  1140
                            }
Dean@729
  1141
                            catch
Dean@729
  1142
                            {
Dean@910
  1143
                                own = null;
Dean@910
  1144
                                status = Globals.ReturnStatus.Failure;
Dean@729
  1145
                            }
Dean@729
  1146
                        }
Dean@729
  1147
                    }
Dean@633
  1148
                }
Dean@633
  1149
                else // Outgoing
Dean@384
  1150
                {
Dean@910
  1151
                    sts = PEPIdentity.GetFromIdentity(omi, out from);
Dean@636
  1152
Dean@647
  1153
                    // Default
Dean@636
  1154
                    if ((from == null) ||
Dean@910
  1155
                        (from.IsEmpty) ||
Dean@910
  1156
                        (sts != Globals.ReturnStatus.Success))
Dean@636
  1157
                    {
Dean@910
  1158
                        sts = PEPIdentity.GetDefaultFromIdentity(out from);
Dean@636
  1159
                    }
Dean@636
  1160
Dean@910
  1161
                    if ((from != null) &&
Dean@910
  1162
                        (sts == Globals.ReturnStatus.Success))
Dean@910
  1163
                    {
Dean@910
  1164
                        /* Note: while From could be used directly, call GetMyIdentity on the address to ensure
Dean@910
  1165
                         * it is an active account in Outlook or registered if new.
Dean@910
  1166
                         */
Dean@910
  1167
                        status = PEPIdentity.GetOwnIdentity(from.Address, out own);
Dean@910
  1168
                    }
Dean@910
  1169
                    else
Dean@910
  1170
                    {
Dean@910
  1171
                        own = null;
Dean@910
  1172
                        status = Globals.ReturnStatus.Failure;
Dean@910
  1173
                    }
Dean@633
  1174
                }
Dean@633
  1175
            }
Dean@910
  1176
            catch (Exception ex)
Dean@910
  1177
            {
Dean@910
  1178
                status = Globals.ReturnStatus.Failure;
Dean@1249
  1179
                Log.Error("GetOwnIdentity: Failure occured, " + ex.ToString());
Dean@910
  1180
            }
Dean@633
  1181
            finally
Dean@633
  1182
            {
Dean@633
  1183
                // Release objects
Dean@633
  1184
                if (account != null)
Dean@633
  1185
                {
vb@1507
  1186
                    // Marshal.ReleaseComObject(account);
Dean@633
  1187
                    account = null;
Dean@384
  1188
                }
Dean@384
  1189
Dean@633
  1190
                if (accounts != null)
Dean@384
  1191
                {
vb@1507
  1192
                    // Marshal.ReleaseComObject(accounts);
Dean@633
  1193
                    accounts = null;
Dean@384
  1194
                }
Dean@384
  1195
Dean@633
  1196
                if (ns != null)
Dean@633
  1197
                {
vb@1507
  1198
                    // Marshal.ReleaseComObject(ns);
Dean@633
  1199
                    ns = null;
Dean@633
  1200
                }
Dean@633
  1201
Dean@633
  1202
                if (currUser != null)
Dean@633
  1203
                {
vb@1507
  1204
                    // Marshal.ReleaseComObject(currUser);
Dean@633
  1205
                    currUser = null;
Dean@633
  1206
                }
Dean@384
  1207
            }
Dean@384
  1208
Dean@910
  1209
            ownIdentity = own;
Dean@910
  1210
            return (status);
Dean@384
  1211
        }
Dean@384
  1212
Dean@384
  1213
        /// <summary>
Dean@1455
  1214
        /// Gets an own identity using the given Outlook account.
Dean@1455
  1215
        /// Warning: The result can be null, fingerprint is not returned.
Dean@1455
  1216
        /// </summary>
Dean@1455
  1217
        /// <param name="account">The account to get the own identity from.</param>
Dean@1455
  1218
        /// <param name="ownIdentity">The output own identity (may be null).</param>
Dean@1455
  1219
        /// <returns>The own identity or null.</returns>
Dean@1455
  1220
        public static Globals.ReturnStatus GetOwnIdentity(Outlook.Account account,
Dean@1455
  1221
                                                          out PEPIdentity ownIdentity)
Dean@1455
  1222
        {
Dean@1455
  1223
            PEPIdentity newIdentity = null;
Dean@1455
  1224
            Outlook.Recipient currUser = null;
Dean@1455
  1225
            Outlook.ExchangeUser currExchUser = null;
Dean@1455
  1226
            Outlook.AddressEntry currAddrEntry = null;
Dean@1455
  1227
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@1455
  1228
Dean@1455
  1229
            try
Dean@1455
  1230
            {
Dean@1455
  1231
                if (account != null)
Dean@1455
  1232
                {
Dean@1455
  1233
                    currUser = account.CurrentUser;
Dean@1455
  1234
Dean@1455
  1235
                    // Attempt to get the address entry
Dean@1455
  1236
                    try
Dean@1455
  1237
                    {
Dean@1455
  1238
                        currAddrEntry = currUser.AddressEntry;
Dean@1455
  1239
                    }
Dean@1455
  1240
                    catch
Dean@1455
  1241
                    {
Dean@1455
  1242
                        currAddrEntry = null;
Dean@1455
  1243
                    }
Dean@1455
  1244
Dean@1455
  1245
                    // Try to get an exchange user
Dean@1455
  1246
                    if ((currAddrEntry != null) &&
Dean@1455
  1247
                        (string.Equals(currAddrEntry.Type, "EX", StringComparison.OrdinalIgnoreCase)))
Dean@1455
  1248
                    {
Dean@1455
  1249
                        try
Dean@1455
  1250
                        {
Dean@1455
  1251
                            currExchUser = currAddrEntry.GetExchangeUser();
Dean@1455
  1252
                        }
Dean@1455
  1253
                        catch
Dean@1455
  1254
                        {
Dean@1455
  1255
                            // Assume the failure was because there is no connection to exchange
Dean@1455
  1256
                            status = Globals.ReturnStatus.FailureNoConnection;
Dean@1455
  1257
                        }
Dean@1455
  1258
                    }
Dean@1455
  1259
Dean@1455
  1260
                    // Create identity
Dean@1455
  1261
                    newIdentity = new PEPIdentity();
Dean@1455
  1262
                    newIdentity.Address = account.SmtpAddress?.Trim();
Dean@1455
  1263
Dean@1455
  1264
                    // Use Exchange information
Dean@1455
  1265
                    if (currExchUser != null)
Dean@1455
  1266
                    {
Dean@1455
  1267
                        newIdentity.UserName = currExchUser.Name?.Trim();
Dean@1455
  1268
                    }
Dean@1455
  1269
                    // Use current user recipient information
Dean@1455
  1270
                    else if (currUser != null)
Dean@1455
  1271
                    {
Dean@1455
  1272
                        newIdentity.UserName = currUser.Name?.Trim();
Dean@1455
  1273
                    }
Dean@1455
  1274
Dean@1455
  1275
                    // Add user ID
Dean@1455
  1276
                    newIdentity.UserId = Globals.ThisAddIn.GetUserId(newIdentity.Address, null);
Dean@1455
  1277
                }
Dean@1455
  1278
            }
Dean@1455
  1279
            catch (Exception ex)
Dean@1455
  1280
            {
Dean@1455
  1281
                status = Globals.ReturnStatus.Failure;
Dean@1455
  1282
                Log.Error("GetOwnIdentity: Failure occured, " + ex.ToString());
Dean@1455
  1283
            }
Dean@1455
  1284
            finally
Dean@1455
  1285
            {
Dean@1455
  1286
                if (currUser != null)
Dean@1455
  1287
                {
vb@1507
  1288
                    // Marshal.ReleaseComObject(currUser);
Dean@1455
  1289
                    currUser = null;
Dean@1455
  1290
                }
Dean@1455
  1291
Dean@1455
  1292
                if (currExchUser != null)
Dean@1455
  1293
                {
vb@1507
  1294
                    // Marshal.ReleaseComObject(currExchUser);
Dean@1455
  1295
                    currExchUser = null;
Dean@1455
  1296
                }
Dean@1455
  1297
Dean@1455
  1298
                if (currAddrEntry != null)
Dean@1455
  1299
                {
vb@1507
  1300
                    // Marshal.ReleaseComObject(currAddrEntry);
Dean@1455
  1301
                    currAddrEntry = null;
Dean@1455
  1302
                }
Dean@1455
  1303
            }
Dean@1455
  1304
Dean@1455
  1305
            ownIdentity = newIdentity;
Dean@1455
  1306
            return (status);
Dean@1455
  1307
        }
Dean@1455
  1308
Dean@1455
  1309
        /// <summary>
Dean@643
  1310
        /// Gets the from/sender user name from the given outlook mail item.
Dean@647
  1311
        /// Only the sender fields of the outlook mail item will be used (SendUsingAccount is ignored).
Dean@647
  1312
        /// This should only be used for messages that have already been sent/received (not draft).
Dean@910
  1313
        /// Warning: The result can be null.
Dean@643
  1314
        /// </summary>
Dean@643
  1315
        /// <param name="omi">The outlook mail item to get the from/sender name from.</param>
Dean@1348
  1316
        /// <param name="fromUserName">The output from/sender user name (may be null).</param>
Dean@910
  1317
        /// <returns>The status of the method.</returns>
Dean@1348
  1318
        public static Globals.ReturnStatus GetFromUserName(Outlook.MailItem omi,
Dean@1348
  1319
                                                           out string fromUserName)
Dean@643
  1320
        {
Dean@1348
  1321
            string userName = null;
Dean@643
  1322
            Outlook.AddressEntry sender = null;
Dean@717
  1323
            Outlook.ExchangeUser exchSender = null;
Dean@910
  1324
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@643
  1325
Dean@910
  1326
            // Note: see https://msdn.microsoft.com/en-us/library/office/ff184624.aspx
Dean@910
  1327
            try
Dean@643
  1328
            {
Dean@910
  1329
                try
Dean@717
  1330
                {
Dean@910
  1331
                    sender = omi.Sender;
Dean@910
  1332
                }
Dean@910
  1333
                catch { }
Dean@910
  1334
Dean@910
  1335
                // Try to handle exchange using an exchange user
Dean@910
  1336
                if ((status != Globals.ReturnStatus.Success) &&
Dean@910
  1337
                    (omi.SenderEmailType == "EX") &&
Dean@910
  1338
                    (sender != null))
Dean@910
  1339
                {
Dean@910
  1340
                    // Common failures occur here when an Exchange server is unavailable but required.
Dean@910
  1341
                    // ExchangeConnectionMode could be checked but a global try/catch is sufficient.
Dean@910
  1342
                    try
Dean@717
  1343
                    {
Dean@910
  1344
                        if (sender.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry ||
Dean@910
  1345
                            sender.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
Dean@717
  1346
                        {
Dean@910
  1347
                            exchSender = sender.GetExchangeUser();
Dean@910
  1348
                            if (exchSender != null)
Dean@910
  1349
                            {
Dean@1348
  1350
                                userName = exchSender.Name;
Dean@910
  1351
                                status = Globals.ReturnStatus.Success;
Dean@910
  1352
                            }
Dean@910
  1353
                            else
Dean@910
  1354
                            {
Dean@910
  1355
                                // Failed to access Exchange sender information
Dean@910
  1356
                                // Other methods will still be tried, if they fail too null will be returned
Dean@910
  1357
                            }
Dean@717
  1358
                        }
Dean@717
  1359
                        else
Dean@717
  1360
                        {
Dean@1348
  1361
                            userName = sender.Name;
Dean@910
  1362
                            status = Globals.ReturnStatus.Success;
Dean@717
  1363
                        }
Dean@717
  1364
                    }
Dean@910
  1365
                    catch
Dean@717
  1366
                    {
Dean@910
  1367
                        // Assume the failure was because there is no connection to exchange
Dean@910
  1368
                        // Other methods will still be tried, if they fail too null will be returned
Dean@910
  1369
                        status = Globals.ReturnStatus.FailureNoConnection;
Dean@717
  1370
                    }
Dean@717
  1371
                }
Dean@910
  1372
Dean@910
  1373
                // Try using the mail item properties (non-exchange)
Dean@910
  1374
                if ((status != Globals.ReturnStatus.Success) &&
Dean@910
  1375
                    (omi.SenderEmailType != "EX") &&
Dean@910
  1376
                    (omi.SenderEmailAddress != null))
Dean@717
  1377
                {
Dean@1348
  1378
                    userName = omi.SenderName;
Dean@910
  1379
                    status = Globals.ReturnStatus.Success;
Dean@717
  1380
                }
Dean@643
  1381
            }
Dean@910
  1382
            catch (Exception ex)
Dean@643
  1383
            {
Dean@910
  1384
                status = Globals.ReturnStatus.Failure;
Dean@1249
  1385
                Log.Error("GetFromUsername: Failure occured, " + ex.ToString());
Dean@910
  1386
            }
Dean@910
  1387
            finally
Dean@910
  1388
            {
Dean@910
  1389
                // Release objects
Dean@910
  1390
                if (sender != null)
Dean@910
  1391
                {
vb@1516
  1392
                    // Marshal.ReleaseComObject(sender);
Dean@910
  1393
                    sender = null;
Dean@910
  1394
                }
Dean@910
  1395
Dean@910
  1396
                if (exchSender != null)
Dean@910
  1397
                {
vb@1516
  1398
                    // Marshal.ReleaseComObject(exchSender);
Dean@910
  1399
                    exchSender = null;
Dean@910
  1400
                }
Dean@643
  1401
            }
Dean@643
  1402
Dean@1348
  1403
            fromUserName = userName;
Dean@910
  1404
            return (status);
Dean@643
  1405
        }
Dean@643
  1406
Dean@643
  1407
        /// <summary>
Dean@643
  1408
        /// Gets the from/sender identity from the given outlook mail item.
Dean@910
  1409
        /// Warning: The result can be null.
Dean@643
  1410
        /// </summary>
Dean@643
  1411
        /// <param name="omi">The outlook mail item to get the from/sender identity from.</param>
Dean@910
  1412
        /// <param name="fromIdentity">The output from/sender identity (may be null).</param>
Dean@910
  1413
        /// <returns>The status of the method.</returns>
Dean@910
  1414
        public static Globals.ReturnStatus GetFromIdentity(Outlook.MailItem omi,
Dean@910
  1415
                                                           out PEPIdentity fromIdentity)
Dean@643
  1416
        {
Thomas@1691
  1417
            bool exchangeUser = false;
Dean@643
  1418
            PEPIdentity from = null;
Dean@765
  1419
            Outlook.ContactItem contact = null;
Dean@643
  1420
            Outlook.AddressEntry sender = null;
Dean@717
  1421
            Outlook.ExchangeUser exchSender = null;
Dean@654
  1422
            Outlook.Account sendingAccount = null;
Dean@910
  1423
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@643
  1424
Dean@910
  1425
            // Note: see https://msdn.microsoft.com/en-us/library/office/ff184624.aspx
Dean@910
  1426
            try
Dean@643
  1427
            {
Dean@1303
  1428
                if (omi.GetIsIncoming())
Dean@654
  1429
                {
Dean@910
  1430
                    // Get sender
Dean@910
  1431
                    try
Dean@717
  1432
                    {
Dean@910
  1433
                        sender = omi.Sender;
Dean@910
  1434
                    }
Dean@910
  1435
                    catch { }
Dean@910
  1436
Thomas@1691
  1437
                    /* SenderEmailType showed to be null in some occasions. Therefore, we need to 
Thomas@1691
  1438
                     * doublecheck if this is an Exchange user.
Thomas@1691
  1439
                     */
Thomas@1691
  1440
                    if (omi.SenderEmailType == "EX")
Thomas@1691
  1441
                    {
Thomas@1691
  1442
                        exchangeUser = true;
Thomas@1691
  1443
                    }
Thomas@1691
  1444
                    else if (omi.SenderEmailType == null)
Thomas@1691
  1445
                    {
Thomas@1691
  1446
                        try
Thomas@1691
  1447
                        {
Thomas@1691
  1448
                            // Exchange address types, see: https://msdn.microsoft.com/en-us/library/office/ff868214.aspx
Thomas@1691
  1449
                            if ((sender != null) &&
Thomas@1691
  1450
                                ((int)sender.AddressEntryUserType <= 5))
Thomas@1691
  1451
                            {
Thomas@1691
  1452
                                exchangeUser = true;
Thomas@1691
  1453
                            }
Thomas@1691
  1454
                        }
Thomas@1691
  1455
                        catch (Exception e)
Thomas@1691
  1456
                        {
Thomas@1691
  1457
                            exchangeUser = false;
Thomas@1691
  1458
                            Log.Error("GetFromIdentity: Error getting email type. " + e.Message);
Thomas@1691
  1459
                        }
Thomas@1691
  1460
                    }
Thomas@1691
  1461
Dean@910
  1462
                    // Try to handle exchange using an exchange user
Dean@910
  1463
                    if ((status != Globals.ReturnStatus.Success) &&
Thomas@1691
  1464
                         exchangeUser &&
Dean@910
  1465
                        (sender != null))
Dean@910
  1466
                    {
Dean@910
  1467
                        // Common failures occur here when an Exchange server is unavailable but required.
Dean@910
  1468
                        // ExchangeConnectionMode could be checked but a global try/catch is sufficient.
Dean@910
  1469
                        try
Dean@717
  1470
                        {
Dean@910
  1471
                            if (sender.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeUserAddressEntry ||
Dean@910
  1472
                                sender.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeRemoteUserAddressEntry)
Dean@910
  1473
                            {
Dean@1348
  1474
                                // Use the ExchangeUser object PrimarySmtpAddress
Dean@910
  1475
                                exchSender = sender.GetExchangeUser();
Dean@910
  1476
                                if (exchSender != null)
Dean@910
  1477
                                {
Dean@910
  1478
                                    from = new PEPIdentity();
Dean@910
  1479
                                    from.Address = exchSender.PrimarySmtpAddress;
Dean@1348
  1480
                                    from.UserName = exchSender.Name;
Dean@910
  1481
Dean@910
  1482
                                    // Add the contact force unencrypted property
Dean@910
  1483
                                    try
Dean@910
  1484
                                    {
Dean@910
  1485
                                        contact = exchSender.GetContact();
Dean@910
  1486
Dean@910
  1487
                                        if (contact != null)
Dean@910
  1488
                                        {
Dean@1304
  1489
                                            from.IsForceUnencrypted = contact.GetForceUnencrypted();
vb@1516
  1490
                                            // Marshal.ReleaseComObject(contact);
Dean@910
  1491
                                            contact = null;
Dean@910
  1492
                                        }
Dean@910
  1493
                                    }
Dean@910
  1494
                                    catch { }
Dean@910
  1495
Dean@1348
  1496
                                    // Add the user ID
Dean@1348
  1497
                                    from.UserId = Globals.ThisAddIn.GetUserId(from.Address, contact);
Dean@910
  1498
Dean@910
  1499
                                    status = Globals.ReturnStatus.Success;
Dean@910
  1500
                                }
Dean@910
  1501
                                else
Dean@910
  1502
                                {
Dean@910
  1503
                                    // Failed to access Exchange sender information
Dean@910
  1504
                                    // Other methods will still be tried, if they fail too null will be returned
Dean@910
  1505
                                }
Dean@910
  1506
                            }
Dean@910
  1507
                            else
Dean@717
  1508
                            {
Dean@717
  1509
                                from = new PEPIdentity();
Dean@1350
  1510
                                from.Address = (string)MapiHelper.GetProperty(sender, MapiProperty.PidTagSmtpAddress);
Dean@1348
  1511
                                from.UserName = sender.Name;
Dean@765
  1512
Dean@765
  1513
                                // Add the contact force unencrypted property
Dean@765
  1514
                                try
Dean@765
  1515
                                {
Dean@910
  1516
                                    contact = sender.GetContact();
Dean@910
  1517
Dean@765
  1518
                                    if (contact != null)
Dean@765
  1519
                                    {
Dean@1304
  1520
                                        from.IsForceUnencrypted = contact.GetForceUnencrypted();
vb@1516
  1521
                                        // Marshal.ReleaseComObject(contact);
Dean@910
  1522
                                        contact = null;
Dean@765
  1523
                                    }
Dean@765
  1524
                                }
Dean@765
  1525
                                catch { }
Dean@776
  1526
Dean@1348
  1527
                                // Add the user ID
Dean@1348
  1528
                                from.UserId = Globals.ThisAddIn.GetUserId(from.Address, contact);
Dean@910
  1529
Dean@910
  1530
                                status = Globals.ReturnStatus.Success;
Dean@717
  1531
                            }
Dean@717
  1532
                        }
Dean@910
  1533
                        catch
Dean@717
  1534
                        {
Dean@910
  1535
                            // Assume the failure was because there is no connection to exchange
Dean@910
  1536
                            // Other methods will still be tried, if they fail too null will be returned
Dean@910
  1537
                            status = Globals.ReturnStatus.FailureNoConnection;
Dean@910
  1538
                        }
Dean@910
  1539
                    }
Dean@776
  1540
Dean@910
  1541
                    // Try using the mail item properties (non-exchange)
Dean@910
  1542
                    if ((status != Globals.ReturnStatus.Success) &&
Thomas@1691
  1543
                        (exchangeUser == false) &&
Dean@910
  1544
                        (omi.SenderEmailAddress != null))
Dean@910
  1545
                    {
Dean@910
  1546
                        from = new PEPIdentity();
Dean@910
  1547
                        from.Address = omi.SenderEmailAddress;
Dean@1348
  1548
                        from.UserName = omi.SenderName;
Dean@910
  1549
Dean@910
  1550
                        // Add the contact force unencrypted property
Dean@910
  1551
                        try
Dean@910
  1552
                        {
Dean@910
  1553
                            contact = sender.GetContact();
Dean@910
  1554
Dean@910
  1555
                            if (contact != null)
Dean@776
  1556
                            {
Dean@1304
  1557
                                from.IsForceUnencrypted = contact.GetForceUnencrypted();
vb@1516
  1558
                                // Marshal.ReleaseComObject(contact);
Dean@776
  1559
                                contact = null;
Dean@776
  1560
                            }
Dean@910
  1561
                        }
Dean@910
  1562
                        catch { }
Dean@765
  1563
Dean@1348
  1564
                        // Add the user ID
Dean@1348
  1565
                        from.UserId = Globals.ThisAddIn.GetUserId(from.Address, contact);
Dean@776
  1566
Dean@910
  1567
                        status = Globals.ReturnStatus.Success;
Dean@717
  1568
                    }
Dean@654
  1569
                }
Dean@910
  1570
                else // Outgoing
Dean@654
  1571
                {
Dean@910
  1572
                    sendingAccount = omi.SendUsingAccount;
Dean@910
  1573
                    if (sendingAccount != null)
Dean@776
  1574
                    {
Dean@910
  1575
                        status = PEPIdentity.GetOwnIdentity(sendingAccount.SmtpAddress, out from);
Dean@776
  1576
                    }
Dean@654
  1577
                }
Dean@643
  1578
            }
Dean@910
  1579
            catch (Exception ex)
Dean@643
  1580
            {
Dean@910
  1581
                status = Globals.ReturnStatus.Failure;
Dean@1249
  1582
                Log.Error("GetFromIdentity: Failure occured, " + ex.ToString());
Dean@910
  1583
            }
Dean@910
  1584
            finally
Dean@910
  1585
            {
Dean@910
  1586
                // Release objects
Dean@910
  1587
                if (contact != null)
Dean@910
  1588
                {
vb@1516
  1589
                    // Marshal.ReleaseComObject(contact);
Dean@910
  1590
                    contact = null;
Dean@910
  1591
                }
Dean@910
  1592
Dean@910
  1593
                if (sender != null)
Dean@910
  1594
                {
vb@1516
  1595
                    // Marshal.ReleaseComObject(sender);
Dean@910
  1596
                    sender = null;
Dean@910
  1597
                }
Dean@910
  1598
Dean@910
  1599
                if (exchSender != null)
Dean@910
  1600
                {
vb@1516
  1601
                    // Marshal.ReleaseComObject(exchSender);
Dean@910
  1602
                    exchSender = null;
Dean@910
  1603
                }
Dean@910
  1604
Dean@654
  1605
                if (sendingAccount != null)
Dean@654
  1606
                {
vb@1507
  1607
                    // Marshal.ReleaseComObject(sendingAccount);
Dean@910
  1608
                    sendingAccount = null;
Dean@654
  1609
                }
Dean@643
  1610
            }
Dean@643
  1611
Dean@910
  1612
            fromIdentity = from;
Dean@910
  1613
            return (status);
Dean@643
  1614
        }
Dean@643
  1615
Dean@643
  1616
        /// <summary>
Dean@643
  1617
        /// Gets the default from/sender identity using the default Outlook user.
Dean@910
  1618
        /// Warning: The result can be null.
Dean@643
  1619
        /// </summary>
Dean@910
  1620
        /// <param name="fromIdentity">The output default from/sender identity (may be null).</param>
Dean@910
  1621
        /// <returns>The status of the method.</returns>
Dean@910
  1622
        public static Globals.ReturnStatus GetDefaultFromIdentity(out PEPIdentity fromIdentity)
Dean@643
  1623
        {
Dean@643
  1624
            PEPIdentity from = null;
Dean@910
  1625
            Outlook.NameSpace ns = null;
Dean@910
  1626
            Outlook.Recipient currUser = null;
Dean@910
  1627
            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
Dean@643
  1628
Dean@910
  1629
            try
Dean@910
  1630
            {
Dean@910
  1631
                ns = Globals.ThisAddIn.Application.Session;
Dean@910
  1632
                currUser = ns.CurrentUser;
Dean@647
  1633
Dean@910
  1634
                if (currUser != null)
Dean@910
  1635
                {
Dean@910
  1636
                    status = PEPIdentity.GetOwnIdentity(currUser.Address, out from);
Dean@910
  1637
                }
Dean@910
  1638
            }
Dean@910
  1639
            catch (Exception ex)
Dean@643
  1640
            {
Dean@910
  1641
                status = Globals.ReturnStatus.Failure;
Dean@1249
  1642
                Log.Error("GetDefaultFromIdentity: Failure occured, " + ex.ToString());
Dean@910
  1643
            }
Dean@910
  1644
            finally
Dean@910
  1645
            {
Dean@910
  1646
                // Release objects
Dean@910
  1647
                if (ns != null)
Dean@910
  1648
                {
vb@1507
  1649
                    // Marshal.ReleaseComObject(ns);
Dean@910
  1650
                    ns = null;
Dean@910
  1651
                }
Dean@910
  1652
Dean@910
  1653
                if (currUser != null)
Dean@910
  1654
                {
vb@1507
  1655
                    // Marshal.ReleaseComObject(currUser);
Dean@910
  1656
                    currUser = null;
Dean@910
  1657
                }
Dean@643
  1658
            }
Dean@643
  1659
Dean@910
  1660
            fromIdentity = from;
Dean@910
  1661
            return (status);
Dean@643
  1662
        }
Dean@643
  1663
Dean@643
  1664
        /// <summary>
Dean@1202
  1665
        /// Creates a new pEp identity from the given outlook recipient.
Dean@910
  1666
        /// The output will never be null.
Dean@910
  1667
        /// Warning: The result can contain identity groups.
Dean@384
  1668
        /// </summary>
Dean@384
  1669
        /// <param name="recipient">The recipient to determine pEp identity for.</param>
Dean@910
  1670
        /// <param name="identity">The output pEp identity of the recipient (will never be null).</param>
Dean@910
  1671
        /// <returns>The status of the method.</returns>
Dean@1202
  1672
        public static Globals.ReturnStatus Create(Outlook.Recipient recipient,
Dean@1202
  1673
                                                  out PEPIdentity identity)
Dean@384
  1674
        {
Thomas@1368
  1675
            string smtpAddress= null;
Dean@749
  1676
            Outlook.AddressEntry addressEntry = null;
Thomas@1368
  1677
            PEPIdentity newIdent = null;
Dean@910
  1678
            Globals.ReturnStatus status = Globals.ReturnStatus.Success;
Dean@384
  1679
Dean@752
  1680
            try
Dean@749
  1681
            {
Dean@961
  1682
                // Get the address entry of the recipient
Dean@749
  1683
                addressEntry = recipient.AddressEntry;
Dean@752
  1684
                if (addressEntry == null)
Dean@752
  1685
                {
Dean@752
  1686
                    // Attempt to resolve if necessary
Dean@752
  1687
                    recipient.Resolve();
Dean@752
  1688
                    addressEntry = recipient.AddressEntry;
Dean@752
  1689
                }
Thomas@1368
  1690
            }
Thomas@1368
  1691
            catch { }
Dean@752
  1692
Thomas@1368
  1693
            // A resolved recipient has an address entry. This should be the common case. If an address entry can be retrieved,
Thomas@1368
  1694
            // run through the full Create() method. If no address entry is available, create a new pEp identity from the recipient.
Thomas@1368
  1695
            if (addressEntry != null)
Thomas@1368
  1696
            {
Thomas@1368
  1697
                status = Create(addressEntry, out newIdent);
Thomas@1368
  1698
            }
Thomas@1368
  1699
            else
Thomas@1368
  1700
            {
Thomas@1368
  1701
                Log.Info("PEPIdentity.Create: Unable to get addressEntry from recipient. Trying to create identity directly.");
Thomas@1368
  1702
Dean@763
  1703
                try
Dean@752
  1704
                {
Thomas@1368
  1705
                    smtpAddress = (string)MapiHelper.GetProperty(recipient, MapiProperty.PidTagSmtpAddress);
Dean@763
  1706
                }
Thomas@1368
  1707
                catch { }
Thomas@1368
  1708
Thomas@1368
  1709
                newIdent = new PEPIdentity
Dean@763
  1710
                {
Thomas@1368
  1711
                    Address = smtpAddress?.Trim(),
Thomas@1368
  1712
                    UserName = recipient?.Name?.Trim()
Thomas@1368
  1713
                };
Dean@763
  1714
Thomas@1368
  1715
                // Get the unique user ID if possible (Assume no contact is available)
Thomas@1368
  1716
                if (string.IsNullOrEmpty(newIdent.Address) == false)
Dean@763
  1717
                {
Thomas@1368
  1718
                    newIdent.UserId = Globals.ThisAddIn.GetUserId(newIdent.Address, null);
Dean@763
  1719
                }
Dean@763
  1720
            }
Thomas@1368
  1721
Thomas@1368
  1722
            // Free resources
Thomas@1368
  1723
            if (addressEntry != null)
Thomas@1368
  1724
            {
vb@1516
  1725
                // Marshal.ReleaseComObject(addressEntry);
Thomas@1368
  1726
                addressEntry = null;
Thomas@1368
  1727
            }
Thomas@1368
  1728
Thomas@1368
  1729
            identity = newIdent;
Thomas@1368
  1730
            return (status);
Thomas@1368
  1731
        }
Thomas@1368
  1732
Thomas@1368
  1733
        /// <summary>
Thomas@1368
  1734
        /// Creates a new pEp identity from the given outlook address entry.
Thomas@1368
  1735
        /// The output will never be null.
Thomas@1368
  1736
        /// Warning: The result can contain identity groups.
Thomas@1368
  1737
        /// </summary>
Thomas@1368
  1738
        /// <param name="addressEntry">The address entry to determine pEp identity for. This should never be null.</param>
Thomas@1368
  1739
        /// <param name="identity">The output pEp identity of the address entry (will never be null).</param>
Thomas@1368
  1740
        /// <returns>The status of the method.</returns>
Thomas@1368
  1741
        public static Globals.ReturnStatus Create(Outlook.AddressEntry addressEntry,
Thomas@1368
  1742
                                                  out PEPIdentity identity)
Thomas@1368
  1743
        {
Thomas@1368
  1744
            bool identityCreated = false;
Thomas@1368
  1745
            bool? forceUnencryptedProperty = null;
Thomas@1368
  1746
            string tempAddress;
Thomas@1368
  1747
            string tempUserName;
Thomas@1368
  1748
            PEPIdentity newIdent = new PEPIdentity();
Thomas@1368
  1749
            PEPIdentity newIdent2;
Thomas@1368
  1750
            PEPIdentity member;
Thomas@1368
  1751
            Outlook.OlAddressEntryUserType? dlType = null;
Thomas@1368
  1752
            Outlook.AddressEntry currAddressEntry = null;
Thomas@1368
  1753
            Outlook.AddressEntry currentMember = null;
Thomas@1368
  1754
            Outlook.ContactItem contact = null;
Thomas@1368
  1755
            Outlook.ContactItem currContact = null;
Thomas@1368
  1756
            Outlook.AddressEntries members = null;
Thomas@1368
  1757
            Outlook.ExchangeDistributionList exchDL = null;
Thomas@1368
  1758
            Outlook.AddressEntries exchDLMembers = null;
Thomas@1368
  1759
            Outlook.ExchangeUser exchUser = null;
Thomas@1368
  1760
            Globals.ReturnStatus sts;
Thomas@1368
  1761
            Globals.ReturnStatus status = Globals.ReturnStatus.Success;
Thomas@1368
  1762
Thomas@1368
  1763
            ///////////////////////////////////////////////////////////
Thomas@1368
  1764
            // Pre-process
Thomas@1368
  1765
            ///////////////////////////////////////////////////////////
Thomas@1368
  1766
Thomas@1368
  1767
            // If address entry is null, no identity can be created and the process can be aborted.
Thomas@1368
  1768
            if (addressEntry == null)
Thomas@1368
  1769
            {
Thomas@1368
  1770
                Log.Error("PEPIdentity.Create: addressEntry is null.");
Thomas@1368
  1771
                identity = new PEPIdentity();
Thomas@1368
  1772
                return Globals.ReturnStatus.Failure;
Thomas@1368
  1773
            }
Thomas@1368
  1774
Thomas@1368
  1775
            try
Thomas@1368
  1776
            {
Thomas@1368
  1777
                if ((addressEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olOutlookDistributionListAddressEntry) ||
Thomas@1368
  1778
                     (addressEntry.AddressEntryUserType == Outlook.OlAddressEntryUserType.olExchangeDistributionListAddressEntry))
Thomas@1368
  1779
                {
Thomas@1368
  1780
                    dlType = addressEntry.AddressEntryUserType;
Thomas@1368
  1781
                }
Thomas@1368
  1782
            }
Thomas@1368
  1783
            catch
Thomas@1368
  1784
            {
Thomas@1368
  1785
                dlType = null;
Thomas@1368
  1786
            }
Thomas@1368
  1787
Thomas@1368
  1788
            // Add the contact force unencrypted property (and get contact)
Thomas@1368
  1789
            try
Thomas@1368
  1790
            {
Thomas@1368
  1791
                // Save contact for later user ID calculation
Thomas@1368
  1792
                contact = addressEntry.GetContact();
Thomas@1368
  1793
                if (contact != null)
Thomas@1368
  1794
                {
Thomas@1368
  1795
                    forceUnencryptedProperty = contact.GetForceUnencrypted();
Thomas@1368
  1796
                }
Thomas@1368
  1797
            }
Thomas@1368
  1798
            catch
Thomas@1368
  1799
            {
Thomas@1368
  1800
                forceUnencryptedProperty = null;
Thomas@1368
  1801
            }
Dean@749
  1802
Dean@1202
  1803
            ///////////////////////////////////////////////////////////
Dean@1202
  1804
            // Handle Outlook distribution lists
Dean@1202
  1805
            ///////////////////////////////////////////////////////////
Dean@1202
  1806
Dean@749
  1807
            // Handle when the recipient is a local Outlook distribution list/contact group
Dean@749
  1808
            if ((identityCreated == false) &&
Dean@1202
  1809
                (dlType != null) &&
Dean@1202
  1810
                (((Outlook.OlAddressEntryUserType)dlType) == Outlook.OlAddressEntryUserType.olOutlookDistributionListAddressEntry))
Dean@384
  1811
            {
Dean@384
  1812
                try
Dean@384
  1813
                {
Thomas@1368
  1814
                    members = addressEntry.Members;
Thomas@1369
  1815
Thomas@1369
  1816
                    try
Thomas@1369
  1817
                    {
Thomas@1369
  1818
                        exchUser = addressEntry.GetExchangeUser();
Thomas@1369
  1819
                    }
Dean@1400
  1820
                    catch
Thomas@1369
  1821
                    {
Thomas@1369
  1822
                        exchUser = null;
Thomas@1369
  1823
                    }
Dean@524
  1824
Thomas@1368
  1825
                    if ((exchUser != null) &&
Thomas@1368
  1826
                        (exchUser.Members != null))
Dean@384
  1827
                    {
Thomas@1368
  1828
                        members = exchUser.Members;
vb@1516
  1829
                        // Marshal.ReleaseComObject(exchUser);
Thomas@1368
  1830
                        exchUser = null;
Thomas@1368
  1831
                    }
Dean@524
  1832
Thomas@1368
  1833
                    if (members != null)
Thomas@1368
  1834
                    {
Thomas@1368
  1835
                        for (int i = 1; i <= members.Count; i++)
Dean@394
  1836
                        {
Thomas@1368
  1837
                            currentMember = members[i];
Dean@723
  1838
Thomas@1368
  1839
                            if (currentMember != null)
Dean@524
  1840
                            {
Thomas@1368
  1841
                                sts = PEPIdentity.Create(currentMember, out member);
Thomas@1368
  1842
                                newIdent.Members.Add(member);
Dean@394
  1843
vb@1516
  1844
                                // Marshal.ReleaseComObject(currentMember);
Thomas@1368
  1845
                                currentMember = null;
Thomas@1368
  1846
                            }
Thomas@1368
  1847
                            else
Thomas@1368
  1848
                            {
Thomas@1368
  1849
                                Log.Error("PEPIdentity.Create: Error getting a local distribution list member.");
Dean@524
  1850
                            }
Dean@394
  1851
                        }
Dean@394
  1852
vb@1516
  1853
                        // Marshal.ReleaseComObject(members);
Thomas@1368
  1854
                        members = null;
Dean@394
  1855
Thomas@1368
  1856
                        identityCreated = true;
Thomas@1368
  1857
                    }
Thomas@1368
  1858
                    else
Thomas@1368
  1859
                    {
Thomas@1368
  1860
                        Log.Error("PEPIdentity.Create: Error getting local distribution list members.");
Dean@394
  1861
                    }
Dean@524
  1862
                }
Dean@524
  1863
                catch
Dean@524
  1864
                {
Dean@524
  1865
                    identityCreated = false;
Dean@524
  1866
                }
Dean@524
  1867
                finally
Dean@524
  1868
                {
Dean@524
  1869
                    // Free resources
Thomas@1368
  1870
                    if (currentMember != null)
Dean@524
  1871
                    {
vb@1516
  1872
                        // Marshal.ReleaseComObject(currentMember);
Thomas@1368
  1873
                        currentMember = null;
Dean@524
  1874
                    }
Dean@394
  1875
Thomas@1368
  1876
                    if (members != null)
Dean@524
  1877
                    {
vb@1516
  1878
                        // Marshal.ReleaseComObject(members);
Thomas@1368
  1879
                        members = null;
Dean@524
  1880
                    }
Dean@524
  1881
Thomas@1368
  1882
                    if (exchUser != null)
Dean@669
  1883
                    {
vb@1516
  1884
                        // Marshal.ReleaseComObject(exchUser);
Thomas@1368
  1885
                        exchUser = null;
Dean@524
  1886
                    }
Dean@394
  1887
                }
Dean@384
  1888
            }
Dean@384
  1889
Dean@1202
  1890
            ///////////////////////////////////////////////////////////
Dean@1202
  1891
            // Handle exchange distribution lists
Dean@1202
  1892
            ///////////////////////////////////////////////////////////
Dean@1202
  1893
Dean@961
  1894
            // Handle when the recipient is an exchange distribution list
Dean@961
  1895
            // See: https://msdn.microsoft.com/en-us/library/office/bb645998.aspx
Dean@749
  1896
            if ((identityCreated == false) &&
Dean@1202
  1897
                (dlType != null) &&
Dean@1202
  1898
                (((Outlook.OlAddressEntryUserType)dlType) == Outlook.OlAddressEntryUserType.olExchangeDistributionListAddressEntry))
Dean@749
  1899
            {
Dean@961
  1900
                try
Dean@961
  1901
                {
Dean@961
  1902
                    exchDL = addressEntry.GetExchangeDistributionList();
Dean@961
  1903
                    exchDLMembers = exchDL.GetExchangeDistributionListMembers();
Dean@749
  1904
Dean@961
  1905
                    // Add group
Dean@961
  1906
                    newIdent = new PEPIdentity();
Dean@961
  1907
                    newIdent.Address = null;
Dean@1348
  1908
                    newIdent.UserName = exchDL.Name;
Dean@1348
  1909
                    newIdent.UserId = null;
Dean@1012
  1910
Dean@961
  1911
                    // Add members
Dean@961
  1912
                    if (exchDLMembers != null)
Dean@961
  1913
                    {
Dean@961
  1914
                        for (int i = 1; i <= exchDLMembers.Count; i++)
Dean@961
  1915
                        {
Dean@961
  1916
                            try
Dean@961
  1917
                            {
Dean@961
  1918
                                currAddressEntry = exchDLMembers[i];
Dean@961
  1919
                                exchUser = currAddressEntry.GetExchangeUser();
Dean@961
  1920
Dean@961
  1921
                                if (exchUser != null)
Dean@961
  1922
                                {
Dean@961
  1923
                                    newIdent2 = new PEPIdentity();
Dean@961
  1924
                                    newIdent2.Address = exchUser.PrimarySmtpAddress;
Dean@1348
  1925
                                    newIdent2.UserName = exchUser.Name;
Dean@961
  1926
Dean@961
  1927
                                    // Add the contact force unencrypted property
Dean@961
  1928
                                    currContact = null;
Dean@961
  1929
                                    try
Dean@961
  1930
                                    {
Dean@961
  1931
                                        currContact = exchUser.GetContact();
Dean@961
  1932
Dean@961
  1933
                                        if (currContact != null)
Dean@961
  1934
                                        {
Dean@1304
  1935
                                            newIdent2.IsForceUnencrypted = currContact.GetForceUnencrypted();
Dean@961
  1936
                                        }
Dean@961
  1937
                                    }
Dean@961
  1938
                                    catch
Dean@961
  1939
                                    {
Dean@961
  1940
                                        currContact = null;
Dean@961
  1941
                                    }
Dean@961
  1942
Dean@1348
  1943
                                    newIdent2.UserId = Globals.ThisAddIn.GetUserId(newIdent2.Address, currContact);
Dean@961
  1944
                                    newIdent.Members.Add(newIdent2);
Dean@961
  1945
                                }
Dean@961
  1946
                            }
Dean@961
  1947
                            catch { }
Dean@961
  1948
                            finally
Dean@961
  1949
                            {
Dean@961
  1950
                                if (currAddressEntry != null)
Dean@961
  1951
                                {
vb@1516
  1952
                                    // Marshal.ReleaseComObject(currAddressEntry);
Dean@961
  1953
                                    currAddressEntry = null;
Dean@961
  1954
                                }
Dean@961
  1955
Dean@961
  1956
                                if (exchUser != null)
Dean@961
  1957
                                {
vb@1516
  1958
                                    // Marshal.ReleaseComObject(exchUser);
Dean@961
  1959
                                    exchUser = null;
Dean@961
  1960
                                }
Dean@961
  1961
Dean@961
  1962
                                if (currContact != null)
Dean@961
  1963
                                {
vb@1516
  1964
                                    // Marshal.ReleaseComObject(currContact);
Dean@961
  1965
                                    currContact = null;
Dean@961
  1966
                                }
Dean@961
  1967
                            }
Dean@961
  1968
                        }
Dean@961
  1969
                    }
Dean@961
  1970
Dean@961
  1971
                    identityCreated = true;
Dean@961
  1972
                }
Dean@961
  1973
                catch { }
Dean@961
  1974
                finally
Dean@961
  1975
                {
Dean@961
  1976
                    if (exchDL != null)
Dean@961
  1977
                    {
vb@1516
  1978
                        // Marshal.ReleaseComObject(exchDL);
Dean@961
  1979
                        exchDL = null;
Dean@961
  1980
                    }
Dean@961
  1981
Dean@961
  1982
                    if (exchDLMembers != null)
Dean@961
  1983
                    {
vb@1516
  1984
                        // Marshal.ReleaseComObject(exchDLMembers);
Dean@961
  1985
                        exchDLMembers = null;
Dean@961
  1986
                    }
Dean@961
  1987
Dean@961
  1988
                    if (currAddressEntry != null)
Dean@961
  1989
                    {
vb@1516
  1990
                        // Marshal.ReleaseComObject(currAddressEntry);
Dean@961
  1991
                        currAddressEntry = null;
Dean@961
  1992
                    }
Dean@961
  1993
Dean@961
  1994
                    if (exchUser != null)
Dean@961
  1995
                    {
vb@1516
  1996
                        // Marshal.ReleaseComObject(exchUser);
Dean@961
  1997
                        exchUser = null;
Dean@961
  1998
                    }
Dean@961
  1999
Dean@961
  2000
                    if (currContact != null)
Dean@961
  2001
                    {
vb@1516
  2002
                        // Marshal.ReleaseComObject(currContact);
Dean@961
  2003
                        currContact = null;
Dean@961
  2004
                    }
Dean@961
  2005
                }
Dean@749
  2006
            }
Dean@749
  2007
Dean@1202
  2008
            ///////////////////////////////////////////////////////////
Dean@394
  2009
            // Handle standard recipients (not lists)
Dean@1202
  2010
            ///////////////////////////////////////////////////////////
Dean@1202
  2011
Dean@394
  2012
            if (identityCreated == false)
Dean@384
  2013
            {
Dean@1202
  2014
                exchUser = null;
Dean@1202
  2015
                tempAddress = null;
Dean@1202
  2016
                tempUserName = null;
Dean@394
  2017
                newIdent = new PEPIdentity();
Dean@763
  2018
                newIdent.IsForceUnencrypted = forceUnencryptedProperty;
Dean@394
  2019
Dean@1202
  2020
                // Handle any exchange users first
Dean@1297
  2021
                try
Dean@1202
  2022
                {
Dean@1297
  2023
                    // Note: Getting the address entry type can throw an exception if the 
Dean@1297
  2024
                    // address entry is invalid (example invalid formatted address in draft email)
Thomas@1368
  2025
                    if (addressEntry.Type == "EX")
Dean@1202
  2026
                    {
Dean@1202
  2027
                        exchUser = addressEntry.GetExchangeUser();
Dean@1202
  2028
                        tempAddress = exchUser.PrimarySmtpAddress;
Dean@1202
  2029
                        tempUserName = exchUser.Name;
Dean@1202
  2030
                    }
Dean@1297
  2031
                }
Dean@1297
  2032
                catch { }
Dean@1297
  2033
                finally
Dean@1297
  2034
                {
Dean@1297
  2035
                    if (exchUser != null)
Dean@1202
  2036
                    {
vb@1516
  2037
                        // Marshal.ReleaseComObject(exchUser);
Dean@1297
  2038
                        exchUser = null;
Dean@1202
  2039
                    }
Dean@1202
  2040
                }
Dean@1202
  2041
Thomas@1368
  2042
                // Get mail address from address entry
Dean@394
  2043
                if (string.IsNullOrWhiteSpace(tempAddress))
Dean@394
  2044
                {
Thomas@1412
  2045
                    try
Thomas@1412
  2046
                    {
Thomas@1412
  2047
                        tempAddress = addressEntry.Address;
Thomas@1412
  2048
                    }
Thomas@1412
  2049
                    catch (Exception e)
Thomas@1412
  2050
                    {
Thomas@1412
  2051
                        Log.Warning("PEPIdentity.Create: Could not get address from addressEntry. " + e.ToString());
Thomas@1412
  2052
                    }
Dean@394
  2053
                }
Dean@394
  2054
Thomas@1368
  2055
                // Get user name from the address entry
Dean@1202
  2056
                if (string.IsNullOrWhiteSpace(tempUserName))
Dean@1202
  2057
                {
Thomas@1368
  2058
                    tempUserName = addressEntry.Name;
Dean@1202
  2059
                }
Dean@1202
  2060
Dean@1202
  2061
                // As a fallback, get information from the associated contact
Dean@394
  2062
                if (string.IsNullOrWhiteSpace(tempAddress))
Dean@394
  2063
                {
Dean@394
  2064
                    try
Dean@394
  2065
                    {
Dean@777
  2066
                        tempAddress = contact.Email1Address;
Dean@1202
  2067
                        tempUserName = contact.Email1DisplayName;
Dean@394
  2068
                    }
Dean@394
  2069
                    catch { }
Dean@394
  2070
                }
Dean@394
  2071
Dean@484
  2072
                // Add address if possible
Dean@484
  2073
                if (string.IsNullOrWhiteSpace(tempAddress) == false)
Dean@394
  2074
                {
Dean@1202
  2075
                    newIdent.Address = tempAddress.Trim();
Dean@394
  2076
                }
Dean@394
  2077
Dean@1348
  2078
                // Add user name if possible
Dean@1202
  2079
                if (string.IsNullOrWhiteSpace(tempUserName) == false)
Dean@1202
  2080
                {
Dean@1348
  2081
                    newIdent.UserName = tempUserName.Trim();
Dean@1202
  2082
                }
Dean@1202
  2083
Dean@484
  2084
                // Get the unique user ID if possible
Dean@1202
  2085
                if (string.IsNullOrEmpty(newIdent.Address) == false)
Dean@484
  2086
                {
Dean@1348
  2087
                    newIdent.UserId = Globals.ThisAddIn.GetUserId(newIdent.Address, contact);
Dean@484
  2088
                }
Dean@394
  2089
Dean@394
  2090
                identityCreated = true;
Dean@384
  2091
            }
Dean@384
  2092
Dean@776
  2093
            // Free resources
Thomas@1368
  2094
            if (addressEntry != null)
Thomas@1368
  2095
            {
vb@1516
  2096
                // Marshal.ReleaseComObject(addressEntry);
Thomas@1368
  2097
                addressEntry = null;
Thomas@1368
  2098
            }
Thomas@1368
  2099
Dean@776
  2100
            if (contact != null)
Dean@776
  2101
            {
vb@1516
  2102
                // Marshal.ReleaseComObject(contact);
Dean@776
  2103
                contact = null;
Dean@776
  2104
            }
Dean@776
  2105
Dean@910
  2106
            identity = newIdent;
Dean@910
  2107
            return (status);
Dean@384
  2108
        }
Dean@384
  2109
Dean@384
  2110
        /// <summary>
Dean@394
  2111
        /// Recursivley converts the given identities into a 'flat' list of any members.
Thomas@1444
  2112
        /// This will remove groups (hierarchy) and convert a group into its members.
Dean@394
  2113
        /// The list will be build by calling each identity's .ToFlatList method.
Dean@394
  2114
        /// </summary>
Dean@394
  2115
        /// <param name="identities">The identities to get the flat list for.</param>
Dean@394
  2116
        /// <returns>The flat list of pEp identities.</returns>
Dean@394
  2117
        public static List<PEPIdentity> ToFlatList(List<PEPIdentity> identities)
Dean@394
  2118
        {
Dean@394
  2119
            List<PEPIdentity> result = new List<PEPIdentity>();
Dean@394
  2120
            List<PEPIdentity> singleList;
Dean@394
  2121
Dean@394
  2122
            for (int i = 0; i < identities.Count; i++)
Dean@394
  2123
            {
Dean@394
  2124
                singleList = identities[i].ToFlatList();
Dean@394
  2125
Dean@394
  2126
                for (int j = 0; j < singleList.Count; j++)
Dean@394
  2127
                {
Dean@394
  2128
                    result.Add(singleList[j]);
Dean@394
  2129
                }
Dean@394
  2130
            }
Dean@394
  2131
Dean@394
  2132
            return (result);
Dean@394
  2133
        }
Dean@384
  2134
    }
Dean@384
  2135
}