Merge pull request #279 from inverse-inc/feature/mail-identities
feat(mail): handle multiple mail identitiespull/282/head
commit
f246d88a5c
|
@ -995,7 +995,7 @@ static NSString *userAgent = nil;
|
||||||
- (void) fetchMailForForwarding: (SOGoMailObject *) sourceMail
|
- (void) fetchMailForForwarding: (SOGoMailObject *) sourceMail
|
||||||
{
|
{
|
||||||
NSDictionary *info, *attachment;
|
NSDictionary *info, *attachment;
|
||||||
NSString *signature, *nl;
|
NSString *signature, *nl, *space;
|
||||||
SOGoUserDefaults *ud;
|
SOGoUserDefaults *ud;
|
||||||
|
|
||||||
[sourceMail fetchCoreInfos];
|
[sourceMail fetchCoreInfos];
|
||||||
|
@ -1031,8 +1031,9 @@ static NSString *userAgent = nil;
|
||||||
signature = [[self mailAccountFolder] signature];
|
signature = [[self mailAccountFolder] signature];
|
||||||
if ([signature length])
|
if ([signature length])
|
||||||
{
|
{
|
||||||
nl = (isHTML ? @"<br/>" : @"\n");
|
nl = (isHTML ? @"<br />" : @"\n");
|
||||||
[self setText: [NSString stringWithFormat: @"%@%@-- %@%@", nl, nl, nl, signature]];
|
space = (isHTML ? @" " : @" ");
|
||||||
|
[self setText: [NSString stringWithFormat: @"%@%@--%@%@%@", nl, nl, space, nl, signature]];
|
||||||
}
|
}
|
||||||
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
attachment = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[sourceMail filenameForForward], @"filename",
|
[sourceMail filenameForForward], @"filename",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2009-2019 Inverse inc.
|
Copyright (C) 2009-2020 Inverse inc.
|
||||||
|
|
||||||
This file is part of SOGo.
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ typedef enum {
|
||||||
forceActivation: (BOOL) forceActivation;
|
forceActivation: (BOOL) forceActivation;
|
||||||
|
|
||||||
- (NSArray *) identities;
|
- (NSArray *) identities;
|
||||||
|
- (NSDictionary *) defaultIdentity;
|
||||||
- (NSString *) signature;
|
- (NSString *) signature;
|
||||||
- (NSString *) encryption;
|
- (NSString *) encryption;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2007-2019 Inverse inc.
|
Copyright (C) 2007-2020 Inverse inc.
|
||||||
|
|
||||||
This file is part of SOGo.
|
This file is part of SOGo.
|
||||||
|
|
||||||
|
@ -667,13 +667,37 @@ static NSString *inboxFolderName = @"INBOX";
|
||||||
return identities;
|
return identities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSDictionary *) defaultIdentity
|
||||||
|
{
|
||||||
|
NSDictionary *defaultIdentity, *currentIdentity;
|
||||||
|
unsigned int count, max;
|
||||||
|
|
||||||
|
defaultIdentity = nil;
|
||||||
|
[self identities];
|
||||||
|
|
||||||
|
max = [identities count];
|
||||||
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
currentIdentity = [identities objectAtIndex: count];
|
||||||
|
if ([[currentIdentity objectForKey: @"isDefault"] boolValue])
|
||||||
|
{
|
||||||
|
defaultIdentity = currentIdentity;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultIdentity; // can be nil
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *) signature
|
- (NSString *) signature
|
||||||
{
|
{
|
||||||
|
NSDictionary *identity;
|
||||||
NSString *signature;
|
NSString *signature;
|
||||||
|
|
||||||
[self identities];
|
identity = [self defaultIdentity];
|
||||||
if ([identities count] > 0)
|
|
||||||
signature = [[identities objectAtIndex: 0] objectForKey: @"signature"];
|
if (identity)
|
||||||
|
signature = [identity objectForKey: @"signature"];
|
||||||
else
|
else
|
||||||
signature = nil;
|
signature = nil;
|
||||||
|
|
||||||
|
|
|
@ -234,14 +234,15 @@
|
||||||
|
|
||||||
- (NSString *) signature
|
- (NSString *) signature
|
||||||
{
|
{
|
||||||
NSString *signature, *mailSignature, *nl;
|
NSString *signature, *mailSignature, *nl, *space;
|
||||||
|
|
||||||
signature = [[sourceMail mailAccountFolder] signature];
|
signature = [[sourceMail mailAccountFolder] signature];
|
||||||
|
|
||||||
if ([signature length])
|
if ([signature length])
|
||||||
{
|
{
|
||||||
nl = (htmlComposition ? @"<br/>" : @"\n");
|
nl = (htmlComposition ? @"<br />" : @"\n");
|
||||||
mailSignature = [NSString stringWithFormat: @"-- %@%@", nl, signature];
|
space = (htmlComposition ? @" " : @" ");
|
||||||
|
mailSignature = [NSString stringWithFormat: @"--%@%@%@", space, nl, signature];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mailSignature = @"";
|
mailSignature = @"";
|
||||||
|
|
|
@ -342,18 +342,34 @@
|
||||||
|
|
||||||
- (NSMutableDictionary *) defaultIdentity
|
- (NSMutableDictionary *) defaultIdentity
|
||||||
{
|
{
|
||||||
NSMutableDictionary *currentIdentity, *defaultIdentity;
|
NSDictionary *defaultAccount, *currentIdentity;
|
||||||
NSEnumerator *identities;
|
NSMutableDictionary *defaultIdentity;
|
||||||
|
NSArray *identities;
|
||||||
|
NSString *defaultEmail;
|
||||||
|
unsigned int count, max;
|
||||||
|
|
||||||
|
defaultEmail = [NSString stringWithFormat: @"%@@%@", [self loginInDomain], [self domain]];
|
||||||
|
defaultAccount = [[self mailAccounts] objectAtIndex: 0];
|
||||||
defaultIdentity = nil;
|
defaultIdentity = nil;
|
||||||
|
|
||||||
identities = [[self allIdentities] objectEnumerator];
|
identities = [defaultAccount objectForKey: @"identities"];
|
||||||
while (!defaultIdentity
|
max = [identities count];
|
||||||
&& (currentIdentity = [identities nextObject]))
|
|
||||||
if ([[currentIdentity objectForKey: @"isDefault"] boolValue])
|
|
||||||
defaultIdentity = currentIdentity;
|
|
||||||
|
|
||||||
return defaultIdentity;
|
for (count = 0; count < max; count++)
|
||||||
|
{
|
||||||
|
currentIdentity = [identities objectAtIndex: count];
|
||||||
|
if ([[currentIdentity objectForKey: @"isDefault"] boolValue])
|
||||||
|
{
|
||||||
|
defaultIdentity = [NSMutableDictionary dictionaryWithDictionary: currentIdentity];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if ([[currentIdentity objectForKey: @"email"] caseInsensitiveCompare: defaultEmail] == NSOrderedSame)
|
||||||
|
{
|
||||||
|
defaultIdentity = [NSMutableDictionary dictionaryWithDictionary: currentIdentity];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultIdentity; // can be nil
|
||||||
}
|
}
|
||||||
|
|
||||||
- (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context
|
- (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context
|
||||||
|
@ -626,19 +642,20 @@
|
||||||
|
|
||||||
- (void) _appendSystemMailAccountWithDelegatedIdentities: (BOOL) appendDeletegatedIdentities
|
- (void) _appendSystemMailAccountWithDelegatedIdentities: (BOOL) appendDeletegatedIdentities
|
||||||
{
|
{
|
||||||
NSString *fullName, *replyTo, *imapLogin, *imapServer, *cImapServer, *signature,
|
NSString *fullName, *imapLogin, *imapServer, *cImapServer,
|
||||||
*encryption, *scheme, *action, *query, *customEmail, *defaultEmail, *sieveServer;
|
*encryption, *scheme, *action, *query, *customEmail, *sieveServer;
|
||||||
NSMutableDictionary *mailAccount, *identity, *mailboxes, *receipts, *security, *mailSettings;
|
NSMutableDictionary *mailAccount, *identity, *mailboxes, *receipts, *security, *mailSettings;
|
||||||
NSNumber *port;
|
NSNumber *port;
|
||||||
NSMutableArray *identities, *mails;
|
NSMutableArray *identities, *mails;
|
||||||
NSArray *delegators, *delegates;
|
NSArray *delegators, *delegates;
|
||||||
NSURL *url, *cUrl;
|
NSURL *url, *cUrl;
|
||||||
unsigned int count, max, default_identity;
|
unsigned int count, max; //, default_identity;
|
||||||
NSInteger defaultPort;
|
NSInteger defaultPort;
|
||||||
NSUInteger index;
|
NSUInteger index;
|
||||||
|
BOOL hasDefaultIdentity;
|
||||||
|
|
||||||
[self userDefaults];
|
[self userDefaults]; // set _defaults
|
||||||
[self userSettings];
|
[self userSettings]; // set _settings
|
||||||
|
|
||||||
mailSettings = [_settings objectForKey: @"Mail"];
|
mailSettings = [_settings objectForKey: @"Mail"];
|
||||||
mailAccount = [NSMutableDictionary new];
|
mailAccount = [NSMutableDictionary new];
|
||||||
|
@ -715,89 +732,75 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Identities
|
// 5. Identities
|
||||||
defaultEmail = [NSString stringWithFormat: @"%@@%@", [self loginInDomain], [self domain]];
|
|
||||||
default_identity = 0;
|
|
||||||
identities = [NSMutableArray new];
|
identities = [NSMutableArray new];
|
||||||
|
[identities addObjectsFromArray: [_defaults mailIdentities]];
|
||||||
mails = [NSMutableArray arrayWithArray: [self allEmails]];
|
mails = [NSMutableArray arrayWithArray: [self allEmails]];
|
||||||
[mailAccount setObject: [mails objectAtIndex: 0] forKey: @"name"];
|
[mailAccount setObject: [mails objectAtIndex: 0] forKey: @"name"];
|
||||||
|
max = [identities count];
|
||||||
|
hasDefaultIdentity = NO;
|
||||||
|
fullName = [self cn];
|
||||||
|
if ([fullName length] == 0)
|
||||||
|
fullName = login;
|
||||||
|
|
||||||
replyTo = [_defaults mailReplyTo];
|
// Sanitize identities
|
||||||
|
|
||||||
max = [mails count];
|
|
||||||
|
|
||||||
/* custom from */
|
|
||||||
if ([[self domainDefaults] mailCustomFromEnabled])
|
|
||||||
{
|
|
||||||
[self userDefaults];
|
|
||||||
customEmail = [_defaults mailCustomEmail];
|
|
||||||
fullName = [_defaults mailCustomFullName];
|
|
||||||
if ([customEmail length] > 0 || [fullName length] > 0)
|
|
||||||
{
|
|
||||||
if ([customEmail length] == 0)
|
|
||||||
customEmail = [mails objectAtIndex: 0];
|
|
||||||
else if ([fullName length] == 0)
|
|
||||||
{
|
|
||||||
// Custom email but default fullname; if the custom email is
|
|
||||||
// one of the user's emails, remove the duplicated entry
|
|
||||||
index = [mails indexOfObject: customEmail];
|
|
||||||
if (index != NSNotFound)
|
|
||||||
{
|
|
||||||
[mails removeObjectAtIndex: index];
|
|
||||||
max--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([fullName length] == 0)
|
|
||||||
{
|
|
||||||
fullName = [self cn];
|
|
||||||
if ([fullName length] == 0)
|
|
||||||
fullName = login;
|
|
||||||
}
|
|
||||||
|
|
||||||
identity = [NSMutableDictionary new];
|
|
||||||
[identity setObject: customEmail forKey: @"email"];
|
|
||||||
[identity setObject: fullName forKey: @"fullName"];
|
|
||||||
|
|
||||||
if ([replyTo length] > 0)
|
|
||||||
[identity setObject: replyTo forKey: @"replyTo"];
|
|
||||||
|
|
||||||
signature = [_defaults mailSignature];
|
|
||||||
if (signature)
|
|
||||||
[identity setObject: signature forKey: @"signature"];
|
|
||||||
[identities addObject: identity];
|
|
||||||
|
|
||||||
if ([[identity objectForKey: @"email"] caseInsensitiveCompare: defaultEmail] == NSOrderedSame)
|
|
||||||
default_identity = [identities count]-1;
|
|
||||||
|
|
||||||
[identity release];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (count = 0; count < max; count++)
|
for (count = 0; count < max; count++)
|
||||||
{
|
{
|
||||||
identity = [NSMutableDictionary new];
|
identity = [NSMutableDictionary dictionaryWithDictionary: [identities objectAtIndex: count]];
|
||||||
fullName = [self cn];
|
customEmail = [identity objectForKey: @"email"];
|
||||||
if (![fullName length])
|
if ([customEmail length])
|
||||||
fullName = login;
|
{
|
||||||
[identity setObject: fullName forKey: @"fullName"];
|
if (![[self domainDefaults] mailCustomFromEnabled])
|
||||||
[identity setObject: [[mails objectAtIndex: count] stringByTrimmingSpaces]
|
{
|
||||||
forKey: @"email"];
|
// No custom from -- enforce a valid email
|
||||||
|
index = [mails indexOfObject: customEmail];
|
||||||
if ([replyTo length] > 0)
|
if (index == NSNotFound)
|
||||||
[identity setObject: replyTo forKey: @"replyTo"];
|
{
|
||||||
|
[identity setObject: [self systemEmail] forKey: @"email"];
|
||||||
signature = [_defaults mailSignature];
|
}
|
||||||
if (signature)
|
}
|
||||||
[identity setObject: signature forKey: @"signature"];
|
}
|
||||||
[identities addObject: identity];
|
else
|
||||||
|
{
|
||||||
if ([[identity objectForKey: @"email"] caseInsensitiveCompare: defaultEmail] == NSOrderedSame)
|
// Email must be defined
|
||||||
default_identity = [identities count]-1;
|
[identity setObject: [self systemEmail] forKey: @"email"];
|
||||||
|
}
|
||||||
[identity release];
|
if (![[self domainDefaults] mailCustomFromEnabled])
|
||||||
|
{
|
||||||
|
// No custom from -- enforce a valid fullname and remove reply-to
|
||||||
|
[identity setObject: fullName forKey: @"fullName"];
|
||||||
|
[identity removeObjectForKey: @"replyTo"];
|
||||||
|
}
|
||||||
|
if (!appendDeletegatedIdentities)
|
||||||
|
{
|
||||||
|
[identity setObject: [NSNumber numberWithBool: YES] forKey: @"isReadOnly"];
|
||||||
|
}
|
||||||
|
if ([[identity objectForKey: @"isDefault"] boolValue])
|
||||||
|
{
|
||||||
|
if (hasDefaultIdentity || !appendDeletegatedIdentities)
|
||||||
|
[identity removeObjectForKey: @"isDefault"]; // only one possible default identity
|
||||||
|
else
|
||||||
|
hasDefaultIdentity = YES;
|
||||||
|
}
|
||||||
|
[identities replaceObjectAtIndex: count withObject: identity];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![identities count])
|
||||||
|
{
|
||||||
|
// Create a default identity
|
||||||
|
identity = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
fullName, @"fullName",
|
||||||
|
[self systemEmail], @"email", nil];
|
||||||
|
if (appendDeletegatedIdentities)
|
||||||
|
{
|
||||||
|
[identity setObject: [NSNumber numberWithBool: YES] forKey: @"isDefault"];
|
||||||
|
hasDefaultIdentity = YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[identity setObject: [NSNumber numberWithBool: YES] forKey: @"isReadOnly"];
|
||||||
|
}
|
||||||
|
[identities addObject: identity];
|
||||||
}
|
}
|
||||||
[[identities objectAtIndex: default_identity] setObject: [NSNumber numberWithBool: YES]
|
|
||||||
forKey: @"isDefault"];
|
|
||||||
|
|
||||||
/* identities from delegators */
|
/* identities from delegators */
|
||||||
if (appendDeletegatedIdentities)
|
if (appendDeletegatedIdentities)
|
||||||
|
@ -980,11 +983,19 @@
|
||||||
|
|
||||||
- (NSDictionary *) primaryIdentity
|
- (NSDictionary *) primaryIdentity
|
||||||
{
|
{
|
||||||
NSDictionary *defaultAccount;
|
NSArray *identities;
|
||||||
|
NSDictionary *defaultIdentity, *defaultAccount;
|
||||||
|
|
||||||
defaultAccount = [[self mailAccounts] objectAtIndex: 0];
|
defaultIdentity = [self defaultIdentity];
|
||||||
|
|
||||||
return [[defaultAccount objectForKey: @"identities"] objectAtIndex: 0];
|
if (!defaultIdentity && [[self mailAccounts] count])
|
||||||
|
{
|
||||||
|
defaultAccount = [[self mailAccounts] objectAtIndex: 0];
|
||||||
|
identities = [defaultAccount objectForKey: @"identities"];
|
||||||
|
defaultIdentity = [identities objectAtIndex: 0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultIdentity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* folders */
|
/* folders */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* SOGoUserDefaults.h - this file is part of SOGo
|
/* SOGoUserDefaults.h - this file is part of SOGo
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2017 Inverse inc.
|
* Copyright (C) 2011-2020 Inverse inc.
|
||||||
*
|
*
|
||||||
* This file is free software; you can redistribute it and/or modify
|
* This file is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -157,21 +157,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
|
||||||
- (void) setMailReplyPlacement: (NSString *) newValue;
|
- (void) setMailReplyPlacement: (NSString *) newValue;
|
||||||
- (NSString *) mailReplyPlacement;
|
- (NSString *) mailReplyPlacement;
|
||||||
|
|
||||||
- (void) setMailSignature: (NSString *) newValue;
|
|
||||||
- (NSString *) mailSignature;
|
|
||||||
|
|
||||||
- (void) setMailSignaturePlacement: (NSString *) newValue;
|
- (void) setMailSignaturePlacement: (NSString *) newValue;
|
||||||
- (NSString *) mailSignaturePlacement;
|
- (NSString *) mailSignaturePlacement;
|
||||||
|
|
||||||
- (void) setMailCustomFullName: (NSString *) newValue;
|
|
||||||
- (NSString *) mailCustomFullName;
|
|
||||||
|
|
||||||
- (void) setMailCustomEmail: (NSString *) newValue;
|
|
||||||
- (NSString *) mailCustomEmail;
|
|
||||||
|
|
||||||
- (void) setMailReplyTo: (NSString *) newValue;
|
|
||||||
- (NSString *) mailReplyTo;
|
|
||||||
|
|
||||||
- (void) setAllowUserReceipt: (BOOL) allow;
|
- (void) setAllowUserReceipt: (BOOL) allow;
|
||||||
- (BOOL) allowUserReceipt;
|
- (BOOL) allowUserReceipt;
|
||||||
- (void) setUserReceiptNonRecipientAction: (NSString *) action;
|
- (void) setUserReceiptNonRecipientAction: (NSString *) action;
|
||||||
|
@ -194,6 +182,9 @@ extern NSString *SOGoWeekStartFirstFullWeek;
|
||||||
- (void) setMailCertificateAlwaysEncrypt: (BOOL) newValue;
|
- (void) setMailCertificateAlwaysEncrypt: (BOOL) newValue;
|
||||||
- (BOOL) mailCertificateAlwaysEncrypt;
|
- (BOOL) mailCertificateAlwaysEncrypt;
|
||||||
|
|
||||||
|
- (void) setMailIdentities: (NSArray *) newIdentites;
|
||||||
|
- (NSArray *) mailIdentities;
|
||||||
|
|
||||||
- (void) setAuxiliaryMailAccounts: (NSArray *) newAccounts;
|
- (void) setAuxiliaryMailAccounts: (NSArray *) newAccounts;
|
||||||
- (NSArray *) auxiliaryMailAccounts;
|
- (NSArray *) auxiliaryMailAccounts;
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#import <Foundation/NSDictionary.h>
|
#import <Foundation/NSDictionary.h>
|
||||||
#import <Foundation/NSTimeZone.h>
|
#import <Foundation/NSTimeZone.h>
|
||||||
|
#import <Foundation/NSValue.h>
|
||||||
|
|
||||||
#import <NGImap4/NSString+Imap4.h>
|
#import <NGImap4/NSString+Imap4.h>
|
||||||
#import <NGObjWeb/WOApplication.h>
|
#import <NGObjWeb/WOApplication.h>
|
||||||
|
@ -114,33 +115,55 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) _migrateSignature
|
- (BOOL) _migrateMailIdentities
|
||||||
{
|
{
|
||||||
BOOL rc;
|
BOOL rc;
|
||||||
NSString *signature;
|
NSArray *mailIdentities;
|
||||||
NSArray *mailAccounts, *identities;
|
NSMutableDictionary *identity;
|
||||||
NSDictionary *identity;
|
NSString *fullName, *email, *replyTo, *signature;
|
||||||
|
|
||||||
mailAccounts = [self arrayForKey: @"MailAccounts"];
|
mailIdentities = [self mailIdentities];
|
||||||
if (mailAccounts)
|
if (mailIdentities)
|
||||||
{
|
{
|
||||||
rc = YES;
|
rc = NO;
|
||||||
if ([mailAccounts count] > 0)
|
|
||||||
{
|
|
||||||
identities = [[mailAccounts objectAtIndex: 0]
|
|
||||||
objectForKey: @"identifies"];
|
|
||||||
if ([identities count] > 0)
|
|
||||||
{
|
|
||||||
identity = [identities objectAtIndex: 0];
|
|
||||||
signature = [identity objectForKey: @"signature"];
|
|
||||||
if ([signature length])
|
|
||||||
[self setObject: signature forKey: @"MailSignature"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[self removeObjectForKey: @"MailAccounts"];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rc = NO;
|
{
|
||||||
|
identity = [NSMutableDictionary dictionaryWithCapacity: 4];
|
||||||
|
fullName = [self stringForKey: @"SOGoMailCustomFullName"];
|
||||||
|
email = [self stringForKey: @"SOGoMailCustomEmail"];
|
||||||
|
replyTo = [self stringForKey: @"SOGoMailReplyTo"];
|
||||||
|
signature = [self stringForKey: @"SOGoMailSignature"];
|
||||||
|
|
||||||
|
if ([fullName length])
|
||||||
|
[identity setObject: fullName forKey: @"fullName"];
|
||||||
|
if ([email length])
|
||||||
|
[identity setObject: email forKey: @"email"];
|
||||||
|
if ([replyTo length])
|
||||||
|
[identity setObject: replyTo forKey: @"replyTo"];
|
||||||
|
if ([signature length])
|
||||||
|
[identity setObject: signature forKey: @"signature"];
|
||||||
|
|
||||||
|
if ([identity count])
|
||||||
|
{
|
||||||
|
[identity setObject: [NSNumber numberWithBool: YES] forKey: @"isDefault"];
|
||||||
|
[self setMailIdentities: [NSArray arrayWithObject: identity]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keep old attributes for now because v2 doesn't handle identities
|
||||||
|
*
|
||||||
|
if (fullName)
|
||||||
|
[self removeObjectForKey: @"SOGoMailCustomFullName"];
|
||||||
|
if (email)
|
||||||
|
[self removeObjectForKey: @"SOGoMailCustomEmail"];
|
||||||
|
if (replyTo)
|
||||||
|
[self removeObjectForKey: @"SOGoMailReplyTo"];
|
||||||
|
if (signature)
|
||||||
|
[self removeObjectForKey: @"SOGoMailSignature"];
|
||||||
|
*/
|
||||||
|
rc = YES;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -211,7 +234,8 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
/* we must not use a boolean operation, otherwise subsequent migrations will
|
/* we must not use a boolean operation, otherwise subsequent migrations will
|
||||||
not be invoked in the case where rc = YES. */
|
not be invoked in the case where rc = YES. */
|
||||||
return ([self _migrateLastModule]
|
return ([self _migrateLastModule]
|
||||||
| [self _migrateSignature]
|
// | [self _migrateSignature]
|
||||||
|
| [self _migrateMailIdentities]
|
||||||
| [self _migrateCalendarCategories]
|
| [self _migrateCalendarCategories]
|
||||||
| [self migrateOldDefaultsWithDictionary: migratedKeys]
|
| [self migrateOldDefaultsWithDictionary: migratedKeys]
|
||||||
| [super migrate]);
|
| [super migrate]);
|
||||||
|
@ -629,18 +653,6 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return [self stringForKey: @"SOGoMailReplyPlacement"];
|
return [self stringForKey: @"SOGoMailReplyPlacement"];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setMailSignature: (NSString *) newValue
|
|
||||||
{
|
|
||||||
if ([newValue length] == 0)
|
|
||||||
newValue = nil;
|
|
||||||
[self setObject: newValue forKey: @"SOGoMailSignature"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) mailSignature
|
|
||||||
{
|
|
||||||
return [self stringForKey: @"SOGoMailSignature"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setMailSignaturePlacement: (NSString *) newValue
|
- (void) setMailSignaturePlacement: (NSString *) newValue
|
||||||
{
|
{
|
||||||
[self setObject: newValue forKey: @"SOGoMailSignaturePlacement"];
|
[self setObject: newValue forKey: @"SOGoMailSignaturePlacement"];
|
||||||
|
@ -660,45 +672,6 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return signaturePlacement;
|
return signaturePlacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setMailCustomFullName: (NSString *) newValue
|
|
||||||
{
|
|
||||||
if ([newValue length] == 0)
|
|
||||||
newValue = nil;
|
|
||||||
[self setObject: [newValue stringByTrimmingSpaces]
|
|
||||||
forKey: @"SOGoMailCustomFullName"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) mailCustomFullName
|
|
||||||
{
|
|
||||||
return [self stringForKey: @"SOGoMailCustomFullName"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setMailCustomEmail: (NSString *) newValue
|
|
||||||
{
|
|
||||||
if ([newValue length] == 0)
|
|
||||||
newValue = nil;
|
|
||||||
[self setObject: [newValue stringByTrimmingSpaces]
|
|
||||||
forKey: @"SOGoMailCustomEmail"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) mailCustomEmail
|
|
||||||
{
|
|
||||||
return [self stringForKey: @"SOGoMailCustomEmail"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setMailReplyTo: (NSString *) newValue
|
|
||||||
{
|
|
||||||
if ([newValue length] == 0)
|
|
||||||
newValue = nil;
|
|
||||||
[self setObject: [newValue stringByTrimmingSpaces]
|
|
||||||
forKey: @"SOGoMailReplyTo"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString *) mailReplyTo
|
|
||||||
{
|
|
||||||
return [self stringForKey: @"SOGoMailReplyTo"];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void) setAllowUserReceipt: (BOOL) allow
|
- (void) setAllowUserReceipt: (BOOL) allow
|
||||||
{
|
{
|
||||||
[self setBool: allow forKey: @"SOGoMailReceiptAllow"];
|
[self setBool: allow forKey: @"SOGoMailReceiptAllow"];
|
||||||
|
@ -784,6 +757,16 @@ NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
|
||||||
return [self boolForKey: @"SOGoMailCertificateAlwaysEncrypt"];
|
return [self boolForKey: @"SOGoMailCertificateAlwaysEncrypt"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) setMailIdentities: (NSArray *) newIdentites
|
||||||
|
{
|
||||||
|
[self setObject: newIdentites forKey: @"SOGoMailIdentities"];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) mailIdentities
|
||||||
|
{
|
||||||
|
return [self arrayForKey: @"SOGoMailIdentities"];
|
||||||
|
}
|
||||||
|
|
||||||
- (void) setAuxiliaryMailAccounts: (NSArray *) newAccounts
|
- (void) setAuxiliaryMailAccounts: (NSArray *) newAccounts
|
||||||
{
|
{
|
||||||
[self setObject: newAccounts forKey: @"AuxiliaryMailAccounts"];
|
[self setObject: newAccounts forKey: @"AuxiliaryMailAccounts"];
|
||||||
|
|
|
@ -674,18 +674,18 @@
|
||||||
return [NSString stringWithFormat: @"urn:uuid:%@", nameInContainer];
|
return [NSString stringWithFormat: @"urn:uuid:%@", nameInContainer];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSException *) setDavSignature: (NSString *) newSignature
|
// - (NSException *) setDavSignature: (NSString *) newSignature
|
||||||
{
|
// {
|
||||||
SOGoUserDefaults *ud;
|
// SOGoUserDefaults *ud;
|
||||||
SOGoUser *user;
|
// SOGoUser *user;
|
||||||
|
|
||||||
user = [SOGoUser userWithLogin: [self ownerInContext: nil]];
|
// user = [SOGoUser userWithLogin: [self ownerInContext: nil]];
|
||||||
ud = [user userDefaults];
|
// ud = [user userDefaults];
|
||||||
[ud setMailSignature: newSignature];
|
// [ud setMailSignature: newSignature];
|
||||||
[ud synchronize];
|
// [ud synchronize];
|
||||||
|
|
||||||
return nil;
|
// return nil;
|
||||||
}
|
// }
|
||||||
|
|
||||||
#warning unused stub
|
#warning unused stub
|
||||||
- (BOOL) collectionDavKey: (NSString *) key
|
- (BOOL) collectionDavKey: (NSString *) key
|
||||||
|
|
|
@ -104,7 +104,7 @@
|
||||||
"To" = "To";
|
"To" = "To";
|
||||||
"Cc" = "Cc";
|
"Cc" = "Cc";
|
||||||
"Bcc" = "Bcc";
|
"Bcc" = "Bcc";
|
||||||
"Reply-To" = "Reply-To";
|
"Reply-To" = "Reply-To";
|
||||||
"Add address" = "Add address";
|
"Add address" = "Add address";
|
||||||
"Body" = "Body";
|
"Body" = "Body";
|
||||||
"Open" = "Open";
|
"Open" = "Open";
|
||||||
|
@ -121,6 +121,7 @@
|
||||||
"Edit Draft..." = "Edit Draft...";
|
"Edit Draft..." = "Edit Draft...";
|
||||||
"Load Images" = "Load Images";
|
"Load Images" = "Load Images";
|
||||||
"Return Receipt" = "Return Receipt";
|
"Return Receipt" = "Return Receipt";
|
||||||
|
"Choose which identity to send this message from" = "Choose which identity to send this message from";
|
||||||
"The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "The sender of this message has asked to be notified when you read this message. Do you wish to notify the sender?";
|
"The sender of this message has asked to be notified when you read this message. Do you with to notify the sender?" = "The sender of this message has asked to be notified when you read this message. Do you wish to notify the sender?";
|
||||||
"Return Receipt (displayed) - %@"= "Return Receipt (displayed) - %@";
|
"Return Receipt (displayed) - %@"= "Return Receipt (displayed) - %@";
|
||||||
"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents.";
|
"This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents." = "This is a Return Receipt for the mail that you sent to %@.\n\nNote: This Return Receipt only acknowledges that the message was displayed on the recipient's computer. There is no guarantee that the recipient has read or understood the message contents.";
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
|
|
||||||
- (WOResponse *) composeAction
|
- (WOResponse *) composeAction
|
||||||
{
|
{
|
||||||
NSString *value, *signature, *nl;
|
NSString *value, *signature, *nl, *space;
|
||||||
SOGoDraftObject *newDraftMessage;
|
SOGoDraftObject *newDraftMessage;
|
||||||
NSMutableDictionary *headers;
|
NSMutableDictionary *headers;
|
||||||
NSDictionary *data;
|
NSDictionary *data;
|
||||||
|
@ -108,7 +108,7 @@
|
||||||
SOGoDraftsFolder *drafts;
|
SOGoDraftsFolder *drafts;
|
||||||
SOGoUserDefaults *ud;
|
SOGoUserDefaults *ud;
|
||||||
id mailTo;
|
id mailTo;
|
||||||
BOOL save;
|
BOOL save, isHTML;
|
||||||
|
|
||||||
drafts = [[self clientObject] draftsFolderInContext: context];
|
drafts = [[self clientObject] draftsFolderInContext: context];
|
||||||
newDraftMessage = [drafts newDraft];
|
newDraftMessage = [drafts newDraft];
|
||||||
|
@ -142,9 +142,11 @@
|
||||||
{
|
{
|
||||||
ud = [[context activeUser] userDefaults];
|
ud = [[context activeUser] userDefaults];
|
||||||
[newDraftMessage setIsHTML: [[ud mailComposeMessageType] isEqualToString: @"html"]];
|
[newDraftMessage setIsHTML: [[ud mailComposeMessageType] isEqualToString: @"html"]];
|
||||||
nl = ([newDraftMessage isHTML] ? @"<br/>" : @"\n");
|
isHTML = [newDraftMessage isHTML];
|
||||||
|
nl = (isHTML? @"<br />" : @"\n");
|
||||||
|
space = (isHTML ? @" " : @" ");
|
||||||
|
|
||||||
[newDraftMessage setText: [NSString stringWithFormat: @"%@%@-- %@%@", nl, nl, nl, signature]];
|
[newDraftMessage setText: [NSString stringWithFormat: @"%@%@--%@%@%@", nl, nl, space, nl, signature]];
|
||||||
save = YES;
|
save = YES;
|
||||||
}
|
}
|
||||||
if (save)
|
if (save)
|
||||||
|
|
|
@ -280,7 +280,7 @@ static NSArray *infoKeys = nil;
|
||||||
}
|
}
|
||||||
if (!from)
|
if (!from)
|
||||||
{
|
{
|
||||||
from = [self _emailFromIdentity: [identities objectAtIndex: 0]];
|
from = [self _emailFromIdentity: [[context activeUser] defaultIdentity]];
|
||||||
[from retain];
|
[from retain];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,19 +301,11 @@ static NSArray *infoKeys = nil;
|
||||||
//
|
//
|
||||||
if ([[[[self clientObject] mailAccountFolder] nameInContainer] intValue] == 0)
|
if ([[[[self clientObject] mailAccountFolder] nameInContainer] intValue] == 0)
|
||||||
{
|
{
|
||||||
SOGoUserDefaults *ud;
|
value = [[[context activeUser] defaultIdentity] objectForKey: @"replyTo"];
|
||||||
|
|
||||||
ud = [[context activeUser] userDefaults];
|
|
||||||
value = [ud mailReplyTo];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSArray *identities;
|
value = [[[[self clientObject] mailAccountFolder] defaultIdentity] objectForKey: @"replyTo"];
|
||||||
|
|
||||||
identities = [[[self clientObject] mailAccountFolder] identities];
|
|
||||||
|
|
||||||
if ([identities count])
|
|
||||||
value = [[identities objectAtIndex: 0] objectForKey: @"replyTo"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
|
@ -757,11 +749,12 @@ static NSArray *infoKeys = nil;
|
||||||
[self setSourceFolder: [co sourceFolder]];
|
[self setSourceFolder: [co sourceFolder]];
|
||||||
|
|
||||||
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
data = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
||||||
[self from], @"from",
|
|
||||||
[self localeCode], @"locale",
|
[self localeCode], @"locale",
|
||||||
[NSNumber numberWithBool: [self isHTML]], @"isHTML",
|
[NSNumber numberWithBool: [self isHTML]], @"isHTML",
|
||||||
text, @"text",
|
text, @"text",
|
||||||
nil];
|
nil];
|
||||||
|
if ((value = [self from]))
|
||||||
|
[data setObject: value forKey: @"from"];
|
||||||
if ((value = [self replyTo]))
|
if ((value = [self replyTo]))
|
||||||
[data setObject: value forKey: @"replyTo"];
|
[data setObject: value forKey: @"replyTo"];
|
||||||
if ((value = [self to]))
|
if ((value = [self to]))
|
||||||
|
|
|
@ -212,6 +212,9 @@
|
||||||
"Email" = "Email";
|
"Email" = "Email";
|
||||||
"Reply To Email" = "Reply To Email";
|
"Reply To Email" = "Reply To Email";
|
||||||
"Signature" = "Signature";
|
"Signature" = "Signature";
|
||||||
|
"Identities" = "Identities";
|
||||||
|
"Default Identity" = "Default Identity";
|
||||||
|
"New Identity" = "New Identity";
|
||||||
"(Click to create)" = "(Click to create)";
|
"(Click to create)" = "(Click to create)";
|
||||||
"Please enter your signature below" = "Please enter your signature below";
|
"Please enter your signature below" = "Please enter your signature below";
|
||||||
"Please specify a valid sender address." = "Please specify a valid sender address.";
|
"Please specify a valid sender address." = "Please specify a valid sender address.";
|
||||||
|
|
|
@ -426,10 +426,13 @@ static SoProduct *preferencesProduct = nil;
|
||||||
}
|
}
|
||||||
if (account)
|
if (account)
|
||||||
[accounts insertObject: account atIndex: 0];
|
[accounts insertObject: account atIndex: 0];
|
||||||
|
[values setObject: accounts forKey: @"AuxiliaryMailAccounts"];
|
||||||
|
|
||||||
|
// Ignore parameters as they are injected in the system mail account ([SOGoUser mailAccounts])
|
||||||
|
[values removeObjectForKey: @"SOGoMailIdentities"];
|
||||||
[values removeObjectForKey: @"SOGoMailCertificate"];
|
[values removeObjectForKey: @"SOGoMailCertificate"];
|
||||||
[values removeObjectForKey: @"SOGoMailCertificateAlwaysSign"];
|
[values removeObjectForKey: @"SOGoMailCertificateAlwaysSign"];
|
||||||
[values removeObjectForKey: @"SOGoMailCertificateAlwaysEncrypt"];
|
[values removeObjectForKey: @"SOGoMailCertificateAlwaysEncrypt"];
|
||||||
[values setObject: accounts forKey: @"AuxiliaryMailAccounts"];
|
|
||||||
|
|
||||||
// Add the domain's default vacation subject if user has not specified a custom subject
|
// Add the domain's default vacation subject if user has not specified a custom subject
|
||||||
vacationOptions = [defaults vacationOptions];
|
vacationOptions = [defaults vacationOptions];
|
||||||
|
|
|
@ -1110,63 +1110,6 @@ static NSArray *reminderValues = nil;
|
||||||
return [[user domainDefaults] mailAuxiliaryUserAccountsEnabled];
|
return [[user domainDefaults] mailAuxiliaryUserAccountsEnabled];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Used internally
|
|
||||||
//
|
|
||||||
- (void) _extractMainIdentity: (NSDictionary *) identity
|
|
||||||
inDictionary: (NSMutableDictionary *) target
|
|
||||||
|
|
||||||
{
|
|
||||||
/* We perform some validation here as we have no guaranty on the input
|
|
||||||
validity. */
|
|
||||||
NSString *value;
|
|
||||||
|
|
||||||
if ([identity isKindOfClass: [NSDictionary class]])
|
|
||||||
{
|
|
||||||
value = [identity objectForKey: @"signature"];
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
[target setObject: value forKey: @"SOGoMailSignature"];
|
|
||||||
else
|
|
||||||
[target removeObjectForKey: @"SOGoMailSignature"];
|
|
||||||
|
|
||||||
if (mailCustomFromEnabled)
|
|
||||||
{
|
|
||||||
value = [[identity objectForKey: @"email"]
|
|
||||||
stringByTrimmingSpaces];
|
|
||||||
|
|
||||||
/* We make sure that the "custom" value is different from the system email */
|
|
||||||
if ([value length] == 0
|
|
||||||
|| [[user systemEmail] isEqualToString: value])
|
|
||||||
value = nil;
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
[target setObject: value forKey: @"SOGoMailCustomEmail"];
|
|
||||||
else
|
|
||||||
[target removeObjectForKey: @"SOGoMailCustomEmail"];
|
|
||||||
|
|
||||||
value = [[identity objectForKey: @"fullName"]
|
|
||||||
stringByTrimmingSpaces];
|
|
||||||
if ([value length] == 0
|
|
||||||
|| [[user cn] isEqualToString: value])
|
|
||||||
value = nil;
|
|
||||||
|
|
||||||
if (value)
|
|
||||||
[target setObject: value forKey: @"SOGoMailCustomFullName"];
|
|
||||||
else
|
|
||||||
[target removeObjectForKey: @"SOGoMailCustomFullName"];
|
|
||||||
}
|
|
||||||
|
|
||||||
value = [[identity objectForKey: @"replyTo"]
|
|
||||||
stringByTrimmingSpaces];
|
|
||||||
|
|
||||||
if (value && [value length] > 0)
|
|
||||||
[target setObject: value forKey: @"SOGoMailReplyTo"];
|
|
||||||
else
|
|
||||||
[target removeObjectForKey: @"SOGoMailReplyTo"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Used internally
|
// Used internally
|
||||||
//
|
//
|
||||||
|
@ -1229,20 +1172,6 @@ static NSArray *reminderValues = nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Used internally
|
|
||||||
//
|
|
||||||
- (void) _extractMainCustomFrom: (NSDictionary *) account
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Used internally
|
|
||||||
//
|
|
||||||
- (void) _extractMainReplyTo: (NSDictionary *) account
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Used internally
|
// Used internally
|
||||||
//
|
//
|
||||||
|
@ -1259,7 +1188,7 @@ static NSArray *reminderValues = nil;
|
||||||
if (!knownKeys)
|
if (!knownKeys)
|
||||||
{
|
{
|
||||||
knownKeys = [NSArray arrayWithObjects: @"fullName", @"email",
|
knownKeys = [NSArray arrayWithObjects: @"fullName", @"email",
|
||||||
@"signature", @"replyTo", nil];
|
@"signature", @"replyTo", @"isDefault", nil];
|
||||||
[knownKeys retain];
|
[knownKeys retain];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,9 +1296,8 @@ static NSArray *reminderValues = nil;
|
||||||
if ([account isKindOfClass: [NSDictionary class]])
|
if ([account isKindOfClass: [NSDictionary class]])
|
||||||
{
|
{
|
||||||
identities = [account objectForKey: @"identities"];
|
identities = [account objectForKey: @"identities"];
|
||||||
if ([identities isKindOfClass: [NSArray class]]
|
if ([self _validateAccountIdentities: identities])
|
||||||
&& [identities count] > 0)
|
[target setObject: identities forKey: @"SOGoMailIdentities"];
|
||||||
[self _extractMainIdentity: [identities objectAtIndex: 0] inDictionary: target];
|
|
||||||
[self _extractMainReceiptsPreferences: [account objectForKey: @"receipts"] inDictionary: target];
|
[self _extractMainReceiptsPreferences: [account objectForKey: @"receipts"] inDictionary: target];
|
||||||
[self _extractMainSecurityPreferences: [account objectForKey: @"security"] inDictionary: target];
|
[self _extractMainSecurityPreferences: [account objectForKey: @"security"] inDictionary: target];
|
||||||
}
|
}
|
||||||
|
@ -1575,10 +1503,6 @@ static NSArray *reminderValues = nil;
|
||||||
if ([accounts count] > 0)
|
if ([accounts count] > 0)
|
||||||
{
|
{
|
||||||
// The first account is the main system account. The following mapping is required:
|
// The first account is the main system account. The following mapping is required:
|
||||||
// - identities[0].signature => SOGoMailSignature
|
|
||||||
// - identities[0].email => SOGoMailCustomEmail
|
|
||||||
// - identities[0].fullName => SOGoMailCustomFullName
|
|
||||||
// - identities[0].replyTo => SOGoMailReplyTo
|
|
||||||
// - receipts.receiptAction => SOGoMailReceiptAllow
|
// - receipts.receiptAction => SOGoMailReceiptAllow
|
||||||
// - receipts.receiptNonRecipientAction => SOGoMailReceiptNonRecipientAction
|
// - receipts.receiptNonRecipientAction => SOGoMailReceiptNonRecipientAction
|
||||||
// - receipts.receiptOutsideDomainAction => SOGoMailReceiptOutsideDomainAction
|
// - receipts.receiptOutsideDomainAction => SOGoMailReceiptOutsideDomainAction
|
||||||
|
|
|
@ -27,10 +27,6 @@
|
||||||
protectedBy = "View";
|
protectedBy = "View";
|
||||||
pageName = "UIxFilterEditor";
|
pageName = "UIxFilterEditor";
|
||||||
};
|
};
|
||||||
identities = {
|
|
||||||
protectedBy = "View";
|
|
||||||
pageName = "UIxIdentities";
|
|
||||||
};
|
|
||||||
activeExternalSieveScripts = {
|
activeExternalSieveScripts = {
|
||||||
protectedBy = "View";
|
protectedBy = "View";
|
||||||
pageName = "UIxJSONPreferences";
|
pageName = "UIxJSONPreferences";
|
||||||
|
|
|
@ -28,14 +28,35 @@
|
||||||
<sg-avatar-image class="hide-xs"
|
<sg-avatar-image class="hide-xs"
|
||||||
sg-email="editor.message.editable.from"
|
sg-email="editor.message.editable.from"
|
||||||
size="32">person</sg-avatar-image>
|
size="32">person</sg-avatar-image>
|
||||||
<md-input-container class="sg-no-wrap">
|
<md-autocomplete
|
||||||
<label><var:string label:value="From"/></label>
|
class="md-margin md-default-theme md-bg md-hue-1" flex="flex"
|
||||||
<md-select name="from"
|
required="required"
|
||||||
ng-model="editor.message.editable.from">
|
md-input-name="from"
|
||||||
<md-option ng-value="identity" ng-repeat="identity in editor.identities track by $index">{{identity}}</md-option>
|
md-require-match="true"
|
||||||
</md-select>
|
md-selected-item="editor.fromIdentity"
|
||||||
</md-input-container>
|
md-search-text="editor.identitySearchText"
|
||||||
<div flex="flex"><!-- spacer --></div>
|
md-selected-item-change="editor.setFromIdentity(identity)"
|
||||||
|
md-items="identity in editor.identitySearch(editor.identitySearchText)"
|
||||||
|
md-item-text="identity.full"
|
||||||
|
md-min-length="0"
|
||||||
|
md-escape-options="clear"
|
||||||
|
label:placeholder="Choose which identity to send this message from"
|
||||||
|
md-menu-class="md-2-line">
|
||||||
|
<md-item-template>
|
||||||
|
<div class="sg-tile-content">
|
||||||
|
<div class="sg-md-subhead">
|
||||||
|
<span md-highlight-text="editor.identitySearchText"
|
||||||
|
md-highlight-flags="gi">{{ identity.full }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="sg-md-body">
|
||||||
|
<i ng-bind-html="editor.account.getTextSignature($index)"><!-- signature --></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</md-item-template>
|
||||||
|
<div ng-messages="messageForm.from.$error">
|
||||||
|
<div ng-message="required">This field is required</div>
|
||||||
|
</div>
|
||||||
|
</md-autocomplete>
|
||||||
<md-button class="sg-icon-button" ng-click="editor.send()"
|
<md-button class="sg-icon-button" ng-click="editor.send()"
|
||||||
ng-disabled="!(editor.message.editable.to.length > 0 || editor.message.editable.cc.length > 0 || editor.message.editable.bcc.length > 0) || editor.uploader.isUploading || messageForm.$invalid || messageForm.$submitted"
|
ng-disabled="!(editor.message.editable.to.length > 0 || editor.message.editable.cc.length > 0 || editor.message.editable.bcc.length > 0) || editor.uploader.isUploading || messageForm.$invalid || messageForm.$submitted"
|
||||||
sg-ripple-click="mailEditor">
|
sg-ripple-click="mailEditor">
|
||||||
|
|
|
@ -94,45 +94,100 @@
|
||||||
</md-input-container>
|
</md-input-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<md-input-container class="md-block md-flex">
|
<!-- identities -->
|
||||||
<label><var:string label:value="Full Name"/></label>
|
<div class="pseudo-input-container" ng-if="$AccountDialogController.hasIdentities()">
|
||||||
<input type="text" required="required"
|
<label class="pseudo-input-label"><var:string label:value="Identities"/></label>
|
||||||
ng-disabled="$AccountDialogController.customFromIsReadonly()"
|
<md-card ng-repeat="identity in $AccountDialogController.account.identities | filter:$AccountDialogController.isEditableIdentity"
|
||||||
ng-model="$AccountDialogController.account.identities[0].fullName"/>
|
class="sg-collapsed"
|
||||||
</md-input-container>
|
ng-class="{ 'sg-expanded': $index == $AccountDialogController.selectedIdentity }">
|
||||||
|
<a class="md-flex md-button" ng-click="$AccountDialogController.selectIdentity($index)">
|
||||||
<div layout="row">
|
<div layout="row" layout-align="start center">
|
||||||
<md-input-container class="md-block" flex="50">
|
<div class="card-picture">
|
||||||
<label><var:string label:value="Email"/></label>
|
<sg-avatar-image class="md-avatar"
|
||||||
<input type="email" required="required"
|
sg-email="identity.email"
|
||||||
ng-disabled="$AccountDialogController.customFromIsReadonly()"
|
size="40">person</sg-avatar-image>
|
||||||
ng-model="$AccountDialogController.account.identities[0].email"/>
|
</div>
|
||||||
</md-input-container>
|
<div class="sg-tile-content">
|
||||||
<md-input-container class="md-block" flex="50"
|
<div class="sg-md-subhead">
|
||||||
ng-hide="$AccountDialogController.customFromIsReadonly()">
|
<div>
|
||||||
<label><var:string label:value="Reply To Email"/></label>
|
<span ng-bind="identity.fullName"><!-- fullName --></span>
|
||||||
<input type="email"
|
<span ng-show="identity.email">
|
||||||
autocomplete="off"
|
<var:entity const:name="nbsp"/>
|
||||||
ng-model="$AccountDialogController.account.identities[0].replyTo"/>
|
<var:entity const:name="lt"/><span ng-bind="identity.email"><!-- email --></span><var:entity const:name="gt"/>
|
||||||
</md-input-container>
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sg-md-body">
|
||||||
|
<i ng-bind-html="$AccountDialogController.account.getTextSignature($index)"><!-- signature --></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<md-button class="sg-icon-button" type="button"
|
||||||
|
ng-click="$AccountDialogController.removeIdentity($index)"
|
||||||
|
ng-show="$AccountDialogController.canRemoveIdentity($index)">
|
||||||
|
<md-icon>delete</md-icon>
|
||||||
|
</md-button>
|
||||||
|
<md-button class="sg-icon-button"
|
||||||
|
label:aria-label="Default Identity"
|
||||||
|
ng-click="$AccountDialogController.setDefaultIdentity($event, $index)">
|
||||||
|
<md-icon ng-class="{ 'md-warn md-hue-2': identity.isDefault }">{{ identity.isDefault ? 'favorite' : 'favorite_border' }}</md-icon>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<md-card-content ng-show="$index == $AccountDialogController.selectedIdentity">
|
||||||
|
<md-input-container class="md-block md-flex">
|
||||||
|
<label><var:string label:value="Full Name"/></label>
|
||||||
|
<input type="text" required="required"
|
||||||
|
ng-disabled="$AccountDialogController.customFromIsReadonly()"
|
||||||
|
ng-model="identity.fullName"/>
|
||||||
|
</md-input-container>
|
||||||
|
<md-autocomplete
|
||||||
|
class="md-block" required="required"
|
||||||
|
md-no-cache="true"
|
||||||
|
md-search-text="identity.email"
|
||||||
|
md-items="address in $AccountDialogController.filterEmailAddresses(identity.email)"
|
||||||
|
md-escape-options="clear"
|
||||||
|
md-require-match="$AccountDialogController.customFromIsReadonly()"
|
||||||
|
md-min-length="0"
|
||||||
|
label:md-floating-label="Email">
|
||||||
|
<md-item-template>
|
||||||
|
<span md-highlight-text="identity.email"
|
||||||
|
md-highlight-flags="gi">{{ address }}</span>
|
||||||
|
</md-item-template>
|
||||||
|
</md-autocomplete>
|
||||||
|
<md-input-container class="md-block"
|
||||||
|
ng-hide="$AccountDialogController.customFromIsReadonly()">
|
||||||
|
<label><var:string label:value="Reply To Email"/></label>
|
||||||
|
<input type="email"
|
||||||
|
autocomplete="off"
|
||||||
|
ng-model="identity.replyTo"/>
|
||||||
|
</md-input-container>
|
||||||
|
<md-input-container
|
||||||
|
class="md-block md-flex"
|
||||||
|
ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'text'">
|
||||||
|
<label><var:string label:value="Signature"/></label>
|
||||||
|
<textarea ng-model="identity.signature"><!-- signature --></textarea>
|
||||||
|
</md-input-container>
|
||||||
|
<div class="pseudo-input-container"
|
||||||
|
ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'html'">
|
||||||
|
<label class="pseudo-input-label"><var:string label:value="Signature"/></label>
|
||||||
|
<sg-ckeditor
|
||||||
|
class="ng-cloak"
|
||||||
|
config="$AccountDialogController.ckConfig"
|
||||||
|
ck-margin="8px"
|
||||||
|
ng-model="identity.signature"><!-- HTML editor --></sg-ckeditor>
|
||||||
|
</div>
|
||||||
|
</md-card-content>
|
||||||
|
</md-card>
|
||||||
|
<div layout="row" layout-align="end center">
|
||||||
|
<md-button type="button"
|
||||||
|
ng-click="$AccountDialogController.addIdentity()"
|
||||||
|
label:aria-label="New Identity">
|
||||||
|
<var:string label:value="New Identity"/>
|
||||||
|
</md-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- To switch between a simple text editor and the CK/HTML editor, we use a ng-if and not
|
<div class="sg-padded--bottom"><!-- spacer --></div>
|
||||||
a ng-class as it doesn't get initialized by the ckEditor class directive -->
|
|
||||||
<md-input-container class="md-block md-flex"
|
|
||||||
ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'text'">
|
|
||||||
<label><var:string label:value="Signature"/></label>
|
|
||||||
<textarea
|
|
||||||
ng-model="$AccountDialogController.account.identities[0].signature"><!-- plain text editor --></textarea>
|
|
||||||
</md-input-container>
|
|
||||||
<div class="pseudo-input-container"
|
|
||||||
ng-if="$AccountDialogController.defaults.SOGoMailComposeMessageType == 'html'">
|
|
||||||
<label class="pseudo-input-label"><var:string label:value="Signature"/></label>
|
|
||||||
<sg-ckeditor
|
|
||||||
config="$AccountDialogController.ckConfig"
|
|
||||||
ck-margin="8px"
|
|
||||||
ng-model="$AccountDialogController.account.identities[0].signature"><!-- HTML editor --></sg-ckeditor>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<md-input-container class="md-block md-input-has-value">
|
<md-input-container class="md-block md-input-has-value">
|
||||||
<label><var:string label:value="When I receive a request for a return receipt"/></label>
|
<label><var:string label:value="When I receive a request for a return receipt"/></label>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit bf5aa3511ef8f849d54818ce1e2ac37f179f6f23
|
Subproject commit 3746148548a304f664c09fcad16ab48a42e7810f
|
|
@ -323,6 +323,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$onDestroy = function () {
|
this.$onDestroy = function () {
|
||||||
|
editorElement.classList.add('ng-cloak');
|
||||||
editor.destroy();
|
editor.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -349,12 +350,19 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// vm.ngModelCtrl.$render();
|
editorElement.classList.remove('ng-cloak');
|
||||||
|
vm.ngModelCtrl.$render();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onEditorChange () {
|
function onEditorChange () {
|
||||||
var html = editor.getData();
|
var html = editor.getData();
|
||||||
var text = editor.document.getBody().getText();
|
var body = editor.document.getBody();
|
||||||
|
var text;
|
||||||
|
|
||||||
|
if (_.isEmpty(body))
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
text = body.getText();
|
||||||
|
|
||||||
if (text === '\n') {
|
if (text === '\n') {
|
||||||
text = '';
|
text = '';
|
||||||
|
|
|
@ -13,10 +13,16 @@
|
||||||
if (typeof futureAccountData.then !== 'function') {
|
if (typeof futureAccountData.then !== 'function') {
|
||||||
angular.extend(this, futureAccountData);
|
angular.extend(this, futureAccountData);
|
||||||
_.forEach(this.identities, function(identity) {
|
_.forEach(this.identities, function(identity) {
|
||||||
if (identity.fullName)
|
if (identity.fullName && identity.email)
|
||||||
identity.full = identity.fullName + ' <' + identity.email + '>';
|
identity.full = identity.fullName + ' <' + identity.email + '>';
|
||||||
else
|
else if (identity.email)
|
||||||
identity.full = '<' + identity.email + '>';
|
identity.full = '<' + identity.email + '>';
|
||||||
|
else
|
||||||
|
identity.full = '';
|
||||||
|
if (identity.signature) {
|
||||||
|
var element = angular.element('<div>' + identity.signature + '</div>');
|
||||||
|
identity.textSignature = _.map(element.contents(), 'textContent').join(' ').trim();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
Account.$log.debug('Account: ' + JSON.stringify(futureAccountData, undefined, 2));
|
Account.$log.debug('Account: ' + JSON.stringify(futureAccountData, undefined, 2));
|
||||||
}
|
}
|
||||||
|
@ -315,6 +321,27 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function getTextSignature
|
||||||
|
* @memberof Account.prototype
|
||||||
|
* @desc Create a plain text representation of the signature for the specified identity index.
|
||||||
|
* @returns a plain text version of the signature
|
||||||
|
*/
|
||||||
|
Account.prototype.getTextSignature = function(index) {
|
||||||
|
if (index < this.identities.length) {
|
||||||
|
var identity = this.identities[index];
|
||||||
|
if (identity.signature) {
|
||||||
|
var element = angular.element('<div>' + identity.signature + '</div>');
|
||||||
|
identity.textSignature = _.map(element.contents(), 'textContent').join(' ').trim();
|
||||||
|
} else {
|
||||||
|
identity.textSignature = '';
|
||||||
|
}
|
||||||
|
return identity.textSignature;
|
||||||
|
} else {
|
||||||
|
throw Error('Index of identity is out of range');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function $certificate
|
* @function $certificate
|
||||||
* @memberof Account.prototype
|
* @memberof Account.prototype
|
||||||
|
@ -451,4 +478,28 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function $omit
|
||||||
|
* @memberof Account.prototype
|
||||||
|
* @desc Return a sanitized object used to send to the server.
|
||||||
|
* @return an object literal copy of the Account instance
|
||||||
|
*/
|
||||||
|
Account.prototype.$omit = function () {
|
||||||
|
var account = {}, identities = [];
|
||||||
|
|
||||||
|
angular.forEach(this, function(value, key) {
|
||||||
|
if (key != 'constructor' && key !='identities' && key[0] != '$') {
|
||||||
|
account[key] = angular.copy(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_.forEach(this.identities, function (identity) {
|
||||||
|
if (!identity.isReadOnly)
|
||||||
|
identities.push(_.pick(identity, ['email', 'fullName', 'replyTo', 'signature', 'isDefault']));
|
||||||
|
});
|
||||||
|
account.identities = identities;
|
||||||
|
|
||||||
|
return account;
|
||||||
|
};
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
this.$onInit = function() {
|
this.$onInit = function() {
|
||||||
$scope.isPopup = stateParent.isPopup;
|
$scope.isPopup = stateParent.isPopup;
|
||||||
this.addRecipient = addRecipient;
|
this.account = stateAccount;
|
||||||
this.autocomplete = {to: {}, cc: {}, bcc: {}};
|
this.autocomplete = {to: {}, cc: {}, bcc: {}};
|
||||||
this.autosave = null;
|
this.autosave = null;
|
||||||
this.autosaveDrafts = autosaveDrafts;
|
this.autosaveDrafts = autosaveDrafts;
|
||||||
|
@ -21,7 +21,9 @@
|
||||||
this.isFullscreen = false;
|
this.isFullscreen = false;
|
||||||
this.hideBcc = (stateMessage.editable.bcc.length === 0);
|
this.hideBcc = (stateMessage.editable.bcc.length === 0);
|
||||||
this.hideCc = (stateMessage.editable.cc.length === 0);
|
this.hideCc = (stateMessage.editable.cc.length === 0);
|
||||||
this.identities = _.uniq(_.map(stateAccount.identities, 'full'));
|
this.identities = stateAccount.identities;
|
||||||
|
this.fromIdentity = stateMessage.editable.from;
|
||||||
|
this.identitySearchText = '';
|
||||||
this.message = stateMessage;
|
this.message = stateMessage;
|
||||||
this.recipientSeparatorKeys = [
|
this.recipientSeparatorKeys = [
|
||||||
$mdConstant.KEY_CODE.ENTER,
|
$mdConstant.KEY_CODE.ENTER,
|
||||||
|
@ -283,11 +285,11 @@
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRecipient(contact, field) {
|
this.addRecipient = function (contact, field) {
|
||||||
var recipients, recipient, list, i, address;
|
var recipients, recipient, list, i, address;
|
||||||
var emailRE = /([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)/i;
|
var emailRE = /([\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+\.)*[\w\!\#$\%\&\'\*\+\-\/\=\?\^\`{\|\}\~]+@((((([a-z0-9]{1}[a-z0-9\-]{0,62}[a-z0-9]{1})|[a-z])\.)+[a-z]{2,})|(\d{1,3}\.){3}\d{1,3}(\:\d{1,5})?)/i;
|
||||||
|
|
||||||
recipients = vm.message.editable[field];
|
recipients = this.message.editable[field];
|
||||||
|
|
||||||
if (angular.isString(contact)) {
|
if (angular.isString(contact)) {
|
||||||
// Examples that are handled:
|
// Examples that are handled:
|
||||||
|
@ -351,11 +353,66 @@
|
||||||
return recipient;
|
return recipient;
|
||||||
else
|
else
|
||||||
return null;
|
return null;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
this.setFromIdentity = function (identity) {
|
||||||
|
var node, children, nl, space, signature, previousIdentity;
|
||||||
|
|
||||||
|
if (identity)
|
||||||
|
this.message.editable.from = identity.full;
|
||||||
|
|
||||||
|
if (this.composeType == "html") {
|
||||||
|
nl = '<br />';
|
||||||
|
space = ' ';
|
||||||
|
} else {
|
||||||
|
nl = '\n';
|
||||||
|
space = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identity && identity.signature)
|
||||||
|
signature = nl + nl + '--' + space + nl + identity.signature;
|
||||||
|
else
|
||||||
|
signature = '';
|
||||||
|
|
||||||
|
previousIdentity = _.find(this.identities, function (currentIdentity, index) {
|
||||||
|
if (currentIdentity.signature) {
|
||||||
|
var currentSignature = new RegExp(nl + ' ?' + nl + '--' + space + nl + currentIdentity.signature);
|
||||||
|
if (vm.message.editable.text.search(currentSignature) >= 0) {
|
||||||
|
vm.message.editable.text = vm.message.editable.text.replace(currentSignature, signature);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!previousIdentity && signature.length > 0) {
|
||||||
|
// Must place signature at proper place
|
||||||
|
if (!this.isNew() && this.replyPlacement == 'above') {
|
||||||
|
var quotedMessageIndex = this.message.editable.text.search(new RegExp(nl + '.+?:( ?' + nl + '){2}(> |<blockquote type="cite")'));
|
||||||
|
if (quotedMessageIndex >= 0) {
|
||||||
|
this.message.editable.text =
|
||||||
|
this.message.editable.text.slice(0, quotedMessageIndex) +
|
||||||
|
signature +
|
||||||
|
this.message.editable.text.slice(quotedMessageIndex);
|
||||||
|
} else {
|
||||||
|
this.message.editable.text = signature + this.message.editable.text;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.message.editable.text += signature;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.identitySearch = function (query) {
|
||||||
|
var q = query ? query : '';
|
||||||
|
return _.filter(stateAccount.identities, function(identity) {
|
||||||
|
return identity.full.toLowerCase().indexOf(q.toLowerCase()) >= 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
this.expandGroup = function(contact, field) {
|
this.expandGroup = function(contact, field) {
|
||||||
var recipients, i, j;
|
var recipients, i, j;
|
||||||
recipients = vm.message.editable[field];
|
recipients = this.message.editable[field];
|
||||||
i = recipients.indexOf(contact);
|
i = recipients.indexOf(contact);
|
||||||
recipients.splice(i, 1);
|
recipients.splice(i, 1);
|
||||||
for (j = 0; j < contact.members.length; j++) {
|
for (j = 0; j < contact.members.length; j++) {
|
||||||
|
@ -391,8 +448,7 @@
|
||||||
if (this.firstFocus) {
|
if (this.firstFocus) {
|
||||||
onCompletePromise().then(function(element) {
|
onCompletePromise().then(function(element) {
|
||||||
var textContent = angular.element(textArea).val(),
|
var textContent = angular.element(textArea).val(),
|
||||||
hasSignature = (Preferences.defaults.SOGoMailSignature &&
|
hasSignature = /\n-- \n/.test(textContent),
|
||||||
Preferences.defaults.SOGoMailSignature.length > 0),
|
|
||||||
signatureLength = 0,
|
signatureLength = 0,
|
||||||
sigLimit,
|
sigLimit,
|
||||||
caretPosition;
|
caretPosition;
|
||||||
|
@ -402,8 +458,9 @@
|
||||||
element.find('md-dialog-content')[0].scrollTop = 0;
|
element.find('md-dialog-content')[0].scrollTop = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// Search for signature starting from bottom
|
||||||
if (hasSignature) {
|
if (hasSignature) {
|
||||||
sigLimit = textContent.lastIndexOf("--");
|
sigLimit = textContent.lastIndexOf("-- ");
|
||||||
if (sigLimit > -1)
|
if (sigLimit > -1)
|
||||||
signatureLength = (textContent.length - sigLimit);
|
signatureLength = (textContent.length - sigLimit);
|
||||||
}
|
}
|
||||||
|
@ -447,7 +504,7 @@
|
||||||
if (x === null) {
|
if (x === null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (x.getText() == '--') {
|
if (/--(%20|%A0|%C2%A0)/.test(encodeURI(x.getText()))) {
|
||||||
node = x.getPrevious().getPrevious();
|
node = x.getPrevious().getPrevious();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,23 +7,23 @@
|
||||||
/**
|
/**
|
||||||
* @ngInject
|
* @ngInject
|
||||||
*/
|
*/
|
||||||
AccountDialogController.$inject = ['$timeout', '$mdDialog', 'FileUploader', 'Dialog', 'sgSettings', 'Account', 'defaults', 'account', 'accountId', 'mailCustomFromEnabled'];
|
AccountDialogController.$inject = ['$timeout', '$window', '$mdConstant', '$mdDialog', 'FileUploader', 'Dialog', 'sgSettings', 'defaults', 'account', 'accountId', 'mailCustomFromEnabled'];
|
||||||
function AccountDialogController($timeout, $mdDialog, FileUploader, Dialog, Settings, Account, defaults, account, accountId, mailCustomFromEnabled) {
|
function AccountDialogController($timeout, $window, $mdConstant, $mdDialog, FileUploader, Dialog, Settings, defaults, account, accountId, mailCustomFromEnabled) {
|
||||||
var vm = this,
|
var vm = this;
|
||||||
accountObject = new Account({ id: accountId, security: account.security });
|
|
||||||
|
|
||||||
vm.defaultPort = 143;
|
this.defaultPort = 143;
|
||||||
vm.defaults = defaults;
|
this.defaults = defaults;
|
||||||
vm.account = account;
|
this.account = account;
|
||||||
vm.accountId = accountId;
|
this.accountId = accountId;
|
||||||
vm.customFromIsReadonly = customFromIsReadonly;
|
this.hostnameRE = accountId > 0 ? /^(?!(127\.0\.0\.1|localhost(?:\.localdomain)?)$)/ : /./;
|
||||||
vm.onBeforeUploadCertificate = onBeforeUploadCertificate;
|
this.addressesSearchText = '';
|
||||||
vm.removeCertificate = removeCertificate;
|
this.emailSeparatorKeys = [
|
||||||
vm.importCertificate = importCertificate;
|
$mdConstant.KEY_CODE.ENTER,
|
||||||
vm.cancel = cancel;
|
$mdConstant.KEY_CODE.TAB,
|
||||||
vm.save = save;
|
$mdConstant.KEY_CODE.COMMA,
|
||||||
vm.hostnameRE = accountId > 0 ? /^(?!(127\.0\.0\.1|localhost(?:\.localdomain)?)$)/ : /./;
|
$mdConstant.KEY_CODE.SEMICOLON
|
||||||
vm.ckConfig = {
|
];
|
||||||
|
this.ckConfig = {
|
||||||
'autoGrow_minHeight': 70,
|
'autoGrow_minHeight': 70,
|
||||||
'toolbar': [['Bold', 'Italic', '-', 'Link',
|
'toolbar': [['Bold', 'Italic', '-', 'Link',
|
||||||
'Font','FontSize','-','TextColor',
|
'Font','FontSize','-','TextColor',
|
||||||
|
@ -31,14 +31,14 @@
|
||||||
language: defaults.LocaleCode
|
language: defaults.LocaleCode
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!vm.account.encryption)
|
if (!this.account.encryption)
|
||||||
vm.account.encryption = "none";
|
this.account.encryption = "none";
|
||||||
else if (vm.account.encryption == "ssl")
|
else if (this.account.encryption == "ssl")
|
||||||
vm.defaultPort = 993;
|
this.defaultPort = 993;
|
||||||
|
|
||||||
_loadCertificate();
|
_loadCertificate();
|
||||||
|
|
||||||
vm.uploader = new FileUploader({
|
this.uploader = new FileUploader({
|
||||||
url: [Settings.activeUser('folderURL') + 'Mail', accountId, 'importCertificate'].join('/'),
|
url: [Settings.activeUser('folderURL') + 'Mail', accountId, 'importCertificate'].join('/'),
|
||||||
autoUpload: false,
|
autoUpload: false,
|
||||||
queueLimit: 1,
|
queueLimit: 1,
|
||||||
|
@ -58,9 +58,65 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.hasIdentities = function () {
|
||||||
|
return _.filter(this.account.identities, vm.isEditableIdentity).length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.isEditableIdentity = function (identity) {
|
||||||
|
return !identity.isReadOnly;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.selectIdentity = function (index) {
|
||||||
|
if (this.selectedIdentity == index) {
|
||||||
|
this.selectedIdentity = null;
|
||||||
|
} else {
|
||||||
|
this.selectedIdentity = index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setDefaultIdentity = function ($event, $index) {
|
||||||
|
_.forEach(this.account.identities, function(identity, i) {
|
||||||
|
if (i == $index)
|
||||||
|
identity.isDefault = !identity.isDefault;
|
||||||
|
else
|
||||||
|
delete identity.isDefault;
|
||||||
|
});
|
||||||
|
$event.stopPropagation();
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.canRemoveIdentity = function (index) {
|
||||||
|
return (index == this.selectedIdentity) && (this.account.identities.length > 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeIdentity = function (index) {
|
||||||
|
this.account.identities.splice(index, 1);
|
||||||
|
this.selectedIdentity = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addIdentity = function () {
|
||||||
|
var firstReadonlyIndex = _.findIndex(this.account.identities, { isReadOnly: 1 });
|
||||||
|
var identity = {};
|
||||||
|
|
||||||
|
if (this.customFromIsReadonly())
|
||||||
|
identity.fullName = this.account.identities[0].fullName;
|
||||||
|
this.account.identities.splice(Math.max(firstReadonlyIndex, 0), 0, identity);
|
||||||
|
this.selectedIdentity = firstReadonlyIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
this.showCkEditor = function ($index) {
|
||||||
|
return this.selectedIdentity == $index && this.defaults.SOGoMailComposeMessageType == 'html';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.filterEmailAddresses = function ($query) {
|
||||||
|
return _.filter($window.defaultEmailAddresses, function (address) {
|
||||||
|
return address.toLowerCase().indexOf($query.toLowerCase()) >= 0;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function _loadCertificate() {
|
function _loadCertificate() {
|
||||||
if (vm.account.security && vm.account.security.hasCertificate)
|
if (vm.account.security && vm.account.security.hasCertificate)
|
||||||
accountObject.$certificate().then(function(crt) {
|
vm.account.$certificate().then(function(crt) {
|
||||||
vm.certificate = crt;
|
vm.certificate = crt;
|
||||||
}, function() {
|
}, function() {
|
||||||
delete vm.account.security.hasCertificate;
|
delete vm.account.security.hasCertificate;
|
||||||
|
@ -73,35 +129,33 @@
|
||||||
return isP12File;
|
return isP12File;
|
||||||
}
|
}
|
||||||
|
|
||||||
function customFromIsReadonly() {
|
this.customFromIsReadonly = function () {
|
||||||
if (accountId > 0)
|
if (accountId > 0)
|
||||||
return false;
|
return false;
|
||||||
return !mailCustomFromEnabled;
|
return !mailCustomFromEnabled;
|
||||||
}
|
};
|
||||||
|
|
||||||
function importCertificate() {
|
this.importCertificate = function () {
|
||||||
vm.uploader.queue[0].formData = [{ password: vm.certificatePassword }];
|
this.uploader.queue[0].formData = [{ password: this.certificatePassword }];
|
||||||
vm.uploader.uploadItem(0);
|
this.uploader.uploadItem(0);
|
||||||
}
|
};
|
||||||
|
|
||||||
function onBeforeUploadCertificate(form) {
|
this.onBeforeUploadCertificate = function (form) {
|
||||||
vm.form = form;
|
this.form = form;
|
||||||
vm.uploader.clearQueue();
|
this.uploader.clearQueue();
|
||||||
}
|
};
|
||||||
|
|
||||||
function removeCertificate() {
|
this.removeCertificate = function () {
|
||||||
accountObject.$removeCertificate().then(function() {
|
this.account.$removeCertificate();
|
||||||
delete vm.account.security.hasCertificate;
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel() {
|
this.cancel = function () {
|
||||||
$mdDialog.cancel();
|
$mdDialog.cancel();
|
||||||
}
|
};
|
||||||
|
|
||||||
function save() {
|
this.save = function () {
|
||||||
$mdDialog.hide();
|
$mdDialog.hide();
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
angular
|
angular
|
||||||
|
|
|
@ -98,28 +98,25 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
this.addMailAccount = function(ev, form) {
|
this.addMailAccount = function(ev, form) {
|
||||||
var account;
|
var account, index;
|
||||||
|
|
||||||
this.preferences.defaults.AuxiliaryMailAccounts.push({});
|
account = new Account({
|
||||||
|
isNew: true,
|
||||||
account = _.last(this.preferences.defaults.AuxiliaryMailAccounts);
|
name: "",
|
||||||
angular.extend(account,
|
identities: [
|
||||||
{
|
{
|
||||||
isNew: true,
|
fullName: "",
|
||||||
name: "",
|
email: ""
|
||||||
identities: [
|
}
|
||||||
{
|
],
|
||||||
fullName: "",
|
receipts: {
|
||||||
email: ""
|
receiptAction: "ignore",
|
||||||
}
|
receiptNonRecipientAction: "ignore",
|
||||||
],
|
receiptOutsideDomainAction: "ignore",
|
||||||
receipts: {
|
receiptAnyAction: "ignore"
|
||||||
receiptAction: "ignore",
|
}
|
||||||
receiptNonRecipientAction: "ignore",
|
});
|
||||||
receiptOutsideDomainAction: "ignore",
|
index = this.preferences.defaults.AuxiliaryMailAccounts.length;
|
||||||
receiptAnyAction: "ignore"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$mdDialog.show({
|
$mdDialog.show({
|
||||||
controller: 'AccountDialogController',
|
controller: 'AccountDialogController',
|
||||||
|
@ -133,14 +130,13 @@
|
||||||
mailCustomFromEnabled: $window.mailCustomFromEnabled
|
mailCustomFromEnabled: $window.mailCustomFromEnabled
|
||||||
}
|
}
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
|
vm.preferences.defaults.AuxiliaryMailAccounts.push(account.$omit());
|
||||||
form.$setDirty();
|
form.$setDirty();
|
||||||
}).catch(function() {
|
|
||||||
vm.preferences.defaults.AuxiliaryMailAccounts.pop();
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.editMailAccount = function(event, index, form) {
|
this.editMailAccount = function(event, index, form) {
|
||||||
var account = this.preferences.defaults.AuxiliaryMailAccounts[index];
|
var account = new Account(this.preferences.defaults.AuxiliaryMailAccounts[index]);
|
||||||
$mdDialog.show({
|
$mdDialog.show({
|
||||||
controller: 'AccountDialogController',
|
controller: 'AccountDialogController',
|
||||||
controllerAs: '$AccountDialogController',
|
controllerAs: '$AccountDialogController',
|
||||||
|
@ -153,10 +149,8 @@
|
||||||
mailCustomFromEnabled: $window.mailCustomFromEnabled
|
mailCustomFromEnabled: $window.mailCustomFromEnabled
|
||||||
}
|
}
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
vm.preferences.defaults.AuxiliaryMailAccounts[index] = account;
|
vm.preferences.defaults.AuxiliaryMailAccounts[index] = account.$omit();
|
||||||
form.$setDirty();
|
form.$setDirty();
|
||||||
}, function() {
|
|
||||||
// Cancel
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,11 @@ $list-item-dense-line-height: 1.05 !default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
md-autocomplete .ng-invalid:not(.ng-empty) {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: $colorRedA700 !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: $layout-breakpoint-xs) {
|
@media (max-width: $layout-breakpoint-xs) {
|
||||||
// Enlarge the autocompletion menu on small devices to fit the entire screen
|
// Enlarge the autocompletion menu on small devices to fit the entire screen
|
||||||
.md-autocomplete-suggestions-container {
|
.md-autocomplete-suggestions-container {
|
||||||
|
|
Loading…
Reference in New Issue