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