mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-15 16:11:01 +00:00
Add support for threaded emails (for 'conversation' view in mail clients)
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@36493 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
27a4a7328c
commit
f410d97aaf
5 changed files with 158 additions and 14 deletions
|
@ -220,6 +220,13 @@
|
|||
* NB. The value of the <em>Subject</em> field is used as a template
|
||||
* in the same way as the <em>Replacement</em> fields.
|
||||
* </p>
|
||||
* <p>The <em>Threaded</em> is just like the Email array except that
|
||||
* it is only used for alarm messages, and the messages sent to the
|
||||
* addresses in this array form a chain of linke messages referring
|
||||
* back to each other rather than all being versions of the same
|
||||
* message. This may give a better effect for people using mail
|
||||
* clients which don't support the message-ID header well.
|
||||
* </p>
|
||||
*
|
||||
* <p>Configuration of the alerter is done by the 'Alerter' key in the user
|
||||
* defaults system. The value for this key must be a dictionary configuring
|
||||
|
@ -293,6 +300,7 @@
|
|||
GSMimeSMTPClient *smtp; /** Client connection to MTA */
|
||||
BOOL debug; /** Debug enabled in config */
|
||||
BOOL supersede; /** If a clear should replace original */
|
||||
BOOL eThreaded; /** alarm reminder emails threaded */
|
||||
}
|
||||
|
||||
/** Called when user defaults are updated, this fetches the dictionary
|
||||
|
|
146
EcAlerter.m
146
EcAlerter.m
|
@ -344,9 +344,9 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
GSMimeDocument *doc;
|
||||
|
||||
doc = AUTORELEASE([GSMimeDocument new]);
|
||||
[doc setHeader: @"subject" value: subject parameters: nil];
|
||||
[doc setHeader: @"to" value: address parameters: nil];
|
||||
[doc setHeader: @"from" value: eFrom parameters: nil];
|
||||
[doc setHeader: @"Subject" value: subject parameters: nil];
|
||||
[doc setHeader: @"To" value: address parameters: nil];
|
||||
[doc setHeader: @"From" value: eFrom parameters: nil];
|
||||
[doc setContent: text type: @"text/plain" name: nil];
|
||||
[[self _smtp] send: doc];
|
||||
}
|
||||
|
@ -660,6 +660,80 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
}
|
||||
NS_ENDHANDLER
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
o = [d objectForKey: @"Threaded"];
|
||||
if ([o isKindOfClass: [NSString class]] == YES)
|
||||
{
|
||||
if ([o hasPrefix: @"("])
|
||||
{
|
||||
o = [(NSString*)o propertyList];
|
||||
}
|
||||
else
|
||||
{
|
||||
o = [NSArray arrayWithObject: o];
|
||||
}
|
||||
}
|
||||
if (o != nil)
|
||||
{
|
||||
NSString *s = [d objectForKey: @"Subject"];
|
||||
|
||||
if (reminder > 0)
|
||||
{
|
||||
NSString *emailIdentifier;
|
||||
NSString *emailInReplyTo;
|
||||
|
||||
if (1 == reminder)
|
||||
{
|
||||
emailInReplyTo = identifier;
|
||||
emailIdentifier
|
||||
= [identifier stringByAppendingString: @"_1"];
|
||||
}
|
||||
else
|
||||
{
|
||||
emailInReplyTo
|
||||
= [NSString stringWithFormat: @"%@_%d",
|
||||
identifier, reminder - 1];
|
||||
emailIdentifier
|
||||
= [NSString stringWithFormat: @"%@_%d",
|
||||
identifier, reminder];
|
||||
}
|
||||
|
||||
[m setObject: emailIdentifier
|
||||
forKey: @"EmailIdentifier"];
|
||||
[m setObject: emailInReplyTo
|
||||
forKey: @"EmailInReplyTo"];
|
||||
}
|
||||
|
||||
if (s != nil)
|
||||
{
|
||||
[m setObject: s forKey: @"Subject"];
|
||||
}
|
||||
|
||||
s = [d objectForKey: @"EmailReplacement"];
|
||||
if (nil == s)
|
||||
{
|
||||
s = [d objectForKey: @"Replacement"];
|
||||
if (nil == s)
|
||||
{
|
||||
/* Full details. */
|
||||
s = @"{Server}({Host}): {Timestamp} {Type}"
|
||||
@" - {Message}";
|
||||
}
|
||||
}
|
||||
[m setObject: s forKey: @"Replacement"];
|
||||
[self mail: m identifier: identifier isClear: isClear to: o];
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"Exception handling Email send for rule: %@",
|
||||
localException);
|
||||
}
|
||||
NS_ENDHANDLER
|
||||
[m removeObjectForKey: @"EmailIdentifier"];
|
||||
[m removeObjectForKey: @"EmailInReplyTo"];
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
o = [d objectForKey: @"Sms"];
|
||||
|
@ -904,15 +978,71 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
|
||||
[self _smtp];
|
||||
doc = AUTORELEASE([GSMimeDocument new]);
|
||||
[doc setHeader: @"subject" value: subject parameters: nil];
|
||||
[doc setHeader: @"Subject" value: subject parameters: nil];
|
||||
[doc setContent: text type: @"text/plain" name: nil];
|
||||
[doc setHeader: @"from" value: eFrom parameters: nil];
|
||||
[doc setHeader: @"From" value: eFrom parameters: nil];
|
||||
|
||||
if ([identifier length] > 0)
|
||||
{
|
||||
NSString *mID;
|
||||
|
||||
mID = [NSString stringWithFormat: @"<alrm%@@%@>", identifier, eBase];
|
||||
/* This may reference an earlier email (for threaded display)
|
||||
*/
|
||||
mID = [m objectForKey: @"EmailInReplyTo"];
|
||||
if (nil != mID)
|
||||
{
|
||||
mID = [NSString stringWithFormat: @"<alrm%@@%@>", mID, eBase];
|
||||
[doc setHeader: @"In-Reply-To" value: mID parameters: nil];
|
||||
}
|
||||
|
||||
/* We may have an identifier set in the dictionary to use
|
||||
*/
|
||||
mID = [m objectForKey: @"EmailIdentifier"];
|
||||
if (nil != mID)
|
||||
{
|
||||
NSRange r = [mID rangeOfString: @"_"];
|
||||
|
||||
if (r.length > 0)
|
||||
{
|
||||
#if 1
|
||||
int version;
|
||||
|
||||
/* Reference all earlier messages in thread.
|
||||
*/
|
||||
version = [[mID substringFromIndex: NSMaxRange(r)] intValue];
|
||||
if (version > 1)
|
||||
{
|
||||
NSMutableString *ms = [NSMutableString string];
|
||||
int index;
|
||||
|
||||
for (index = 1; index < version; index++)
|
||||
{
|
||||
if (index > 1)
|
||||
{
|
||||
[ms appendString: @" "];
|
||||
}
|
||||
[ms appendFormat: @"<alrm%@_%d@%@>",
|
||||
mID, index, eBase];
|
||||
}
|
||||
[doc setHeader: @"References" value: ms parameters: nil];
|
||||
}
|
||||
#else
|
||||
NSString *ref;
|
||||
|
||||
/* Reference the original message at start of thread.
|
||||
*/
|
||||
ref = [NSString stringWithFormat: @"<alrm%@@%@>",
|
||||
[mID substringToIndex: r.location], eBase];
|
||||
[doc setHeader: @"References" value: ref parameters: nil];
|
||||
#endif
|
||||
}
|
||||
mID = [NSString stringWithFormat: @"<alrm%@@%@>", mID, eBase];
|
||||
}
|
||||
else
|
||||
{
|
||||
mID = [NSString stringWithFormat: @"<alrm%@@%@>",
|
||||
identifier, eBase];
|
||||
}
|
||||
|
||||
if (YES == isClear)
|
||||
{
|
||||
|
@ -933,7 +1063,7 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
[doc setHeader: @"Message-ID" value: mID parameters: nil];
|
||||
}
|
||||
}
|
||||
else if ([identifier length] > 0)
|
||||
else
|
||||
{
|
||||
[doc setHeader: @"Message-ID" value: mID parameters: nil];
|
||||
}
|
||||
|
@ -946,7 +1076,7 @@ replaceFields(NSDictionary *fields, NSString *template)
|
|||
GSMimeDocument *msg;
|
||||
|
||||
msg = AUTORELEASE([doc copy]);
|
||||
[msg setHeader: @"to" value: d parameters: nil];
|
||||
[msg setHeader: @"To" value: d parameters: nil];
|
||||
[smtp send: msg];
|
||||
}
|
||||
NS_HANDLER
|
||||
|
|
|
@ -426,7 +426,8 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
|
|||
|
||||
- (NSString*) description
|
||||
{
|
||||
return [NSString stringWithFormat: @"Control server\n%@\n%@", alerter, sink];
|
||||
return [NSString stringWithFormat: @"%@ running since %@\n%@\n%@",
|
||||
[super description], [self ecStarted], alerter, sink];
|
||||
}
|
||||
|
||||
- (oneway void) domanage: (NSString*)name
|
||||
|
|
|
@ -358,6 +358,11 @@ extern NSString* cmdVersion(NSString *ver);
|
|||
*/
|
||||
- (void) ecDoLock;
|
||||
|
||||
/** Return the timestamp at which this process started up (when the
|
||||
* receiver was initialised).
|
||||
*/
|
||||
- (NSDate*) ecStarted;
|
||||
|
||||
/** Release a lock on the shared EcProcess after thread-safe updates to
|
||||
* process-wide variables.
|
||||
*/
|
||||
|
|
10
EcProcess.m
10
EcProcess.m
|
@ -1305,7 +1305,7 @@ static NSString *noFiles = @"No log files to archive";
|
|||
return cmdSignalled;
|
||||
}
|
||||
|
||||
- (NSDate*) cmdStarted
|
||||
- (NSDate*) ecStarted
|
||||
{
|
||||
return started;
|
||||
}
|
||||
|
@ -2788,7 +2788,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
else
|
||||
{
|
||||
[self cmdPrintf: @"\n%@ on %@ running since %@\n\n",
|
||||
cmdLogName(), ecHostName(), [self cmdStarted]];
|
||||
cmdLogName(), ecHostName(), [self ecStarted]];
|
||||
|
||||
if (NO == [cmdDefs boolForKey: @"Memory"])
|
||||
{
|
||||
|
@ -2814,7 +2814,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
else
|
||||
{
|
||||
[self cmdPrintf: @"\n%@ on %@ running since %@\n",
|
||||
cmdLogName(), ecHostName(), [self cmdStarted]];
|
||||
cmdLogName(), ecHostName(), [self ecStarted]];
|
||||
if ([self cmdLastIP] != nil)
|
||||
{
|
||||
[self cmdPrintf: @"Last IP at %@\n", [self cmdLastIP]];
|
||||
|
@ -3005,6 +3005,8 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
|
||||
EcProc = self;
|
||||
|
||||
started = RETAIN([dateClass date]);
|
||||
|
||||
pinfo = [NSProcessInfo processInfo];
|
||||
mgr = [NSFileManager defaultManager];
|
||||
prf = EC_DEFAULTS_PREFIX;
|
||||
|
@ -3208,8 +3210,6 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
|||
}
|
||||
}
|
||||
|
||||
started = RETAIN([dateClass date]);
|
||||
|
||||
/* See if we have a name specified for this process.
|
||||
*/
|
||||
ASSIGN(cmdName, [cmdDefs stringForKey: @"ProgramName"]);
|
||||
|
|
Loading…
Reference in a new issue