[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[coldsync-hackers] fetch-mail conduit and deleting records
Hi there,
first of all, I wrote an fetch-mail conduit, which puts an local
mbox (or only the unread mails of it) into the Inbox of the Palm
and deletes mails in the Inbox of the Palm, which have been read
already.
2 Problems:
1) Even with my md5summing and explicit comparing, I still
have duplicates for unknown reasons :-(
2) Read mails do not get deleted sometimes. So I'm not sure,
whether I do this in the right stage.
I've tried to solve this, by writing an second conduit only
deleting unread messages. But this doesn't seem to help :-(
I'm using coldsync 2.1.3.
Both scripts appended for review.
Thanks & Regards
Ingo Oeser
#!/usr/bin/perl -w
#
# ColdSync Mail fetching conduit, by Ingo Oeser <cs@rameria.de>
#
# Distributed under Artistic License
#
# $Id$
#
use strict;
use Digest::MD5;
use Palm::Mail;
use ColdSync;
use Mail::Internet;
use Mail::Util;
use Mail::Header;
use MIME::QuotedPrint;
# Default values for headers
%HEADERS = (
"Local-Inbox" => "",
"Inbox-name" => "Inbox", # Name of category for incoming mail
"Truncate-After" => 8000, # Truncate body after that amount of bytes
);
my $VERSION = (qw( $Revision: 0.2 $ ))[1]; # Conduit version
my %cat_name2index; # Maps category names to indices
my %rec_hash;
StartConduit("fetch");
$HEADERS{'Truncate-After'}+=0; # Mark it a number
$HEADERS{'Truncate-After'}-=50 if $HEADERS{'Truncate-After'} gt 1000;
$HEADERS{'Truncate-After'}=100 if $HEADERS{'Truncate-After'} lt 100;
$HEADERS{'Truncate-After'}=7950 if $HEADERS{'Truncate-After'} gt 7950;
&map_cats();
# map category number
my $cat = $cat_name2index{$HEADERS{'Inbox-name'}};
&hash_recs();
# append all mail as new records
# TODO: Do this optionally only for unread mail
my @refs=Mail::Util::read_mbox($HEADERS{'Local-Inbox'});
while (($#refs > 0)) {
my $mail=new Mail::Internet(shift @refs);
my $head=$mail->head();
my %headers;
my $body;
my $record;
# clean the mail a little
$mail->remove_sig(); $mail->tidy_body();
my @tags=('From','To','Reply-To','Subject','Cc','Status','Date');
my $key;
foreach $key (@tags) {
my $s=$head->get($key);
$headers{$key}='', next if !(defined($s));
$s=~ s/\n//gm ;
$s=~ s/(\s{1,})/ /gm ;
if ($s =~ /=\?iso-8859-1\?Q\?/i ) {
$s=~s/=\?iso-8859-1\?Q\?(.*?)\?=/$1/i ;
$s=decode_qp($s);
}
$s=~ s/^\s(.*)\s$/$1/ ;
$headers{$key}=$s;
}
# ignore mail already read
next if (defined($headers{'Status:'}) and ($headers{'Status:'} eq 'RO'));
# evaluate the body
$body=join '',@{$mail->body()};
if (length($body) > $HEADERS{'Truncate-After'}) {
$body=substr $body,0,$HEADERS{'Truncate-After'};
$body.="<<<<<<<<<<<<< truncated!!";
}
# build up the actual record
$record = $PDB->new_Record;
$record->{from}='';
$record->{to}='';
$record->{cc}='';
$record->{subject}='';
$record->{replyTo}='';
$record->{sentTo}='';
$record->{from}=$headers{'From'} if $headers{'From'} ne "";
$record->{to}=$headers{'To'} if $headers{'To'} ne "";
$record->{cc}=$headers{'Cc'} if $headers{'Cc'} ne "";
$record->{replyTo}=$headers{'Reply-To'} if $headers{'Reply-To'} ne "";
$record->{subject}=$headers{'Subject'} if $headers{'Subject'} ne "";
$record->{body}=$body, if $body ne '';
$record->{category} = $cat;
# ignore records already in database
next if (defined(&unique_record($record)));
$PDB->append_Record($record);
}
&delete_read_mail();
EndConduit;
sub delete_read_mail() {
my $record;
foreach $record (@{$PDB->{records}})
{
# Skip everything except the Inbox folder
next if ($record->{category} != $cat);
# Delete read records
$PDB->delete_Record($record, 1) if ($record->{is_read});
}
}
# hash contents of database
sub hash_recs() {
my $record;
foreach $record (@{$PDB->{records}})
{
# Skip everything except the Inbox folder
next if ($record->{category} != $cat);
$rec_hash{$record->{id}} = &md5record($record);
}
}
# map category names to category ids
sub map_cats() {
my $i;
for ($i = 0; $i <= $#{$PDB->{appinfo}{categories}}; $i++)
{
$cat_name2index{$PDB->{appinfo}{categories}[$i]{name}} = $i;
}
}
# check, if this record is unique and return undef, if true or the (first)
# duplicate, if false
sub unique_record() {
my $rec = shift;
my $rec2;
my $k; my $v;
my $hash = &md5record($rec);
while (($k,$v) = each %rec_hash) {
next if ($v ne $hash);
$rec2 = $PDB->findRecordByID($k);
next if (!defined($rec2));
next if (!defined($rec2->{from}) or !defined($rec->{from}));
next if (!defined($rec2->{to}) or !defined($rec->{to}));
next if (!defined($rec2->{cc}) or !defined($rec->{cc}));
next if (!defined($rec2->{replyTo}) or !defined($rec->{replyTo}));
next if (!defined($rec2->{subject}) or !defined($rec->{subject}));
next if (!defined($rec2->{body}) or !defined($rec->{body}));
next if ($rec2->{from} ne $rec->{from});
next if ($rec2->{to} ne $rec->{to});
next if ($rec2->{cc} ne $rec->{cc});
next if ($rec2->{replyTo} ne $rec->{replyTo});
next if ($rec2->{subject} ne $rec->{subject});
next if ($rec2->{body} ne $rec->{body});
# yes, this is the first duplicate
return $rec2;
}
# no duplicate item found
return undef;
}
sub md5record() {
my $rec = shift;
my $md5 = Digest::MD5->new;
$md5->reset;
$md5->add($rec->{from}) if (defined($rec->{from}) and ($rec->{from} ne ''));
$md5->add($rec->{to}) if (defined($rec->{to}) and ($rec->{to} ne ''));
$md5->add($rec->{cc}) if (defined($rec->{cc}) and ($rec->{cc} ne ''));
$md5->add($rec->{replyTo}) if (defined($rec->{replyTo}) and ($rec->{replyTo} ne ''));
$md5->add($rec->{subject}) if (defined($rec->{subject}) and ($rec->{subject} ne ''));
$md5->add($rec->{body}) if (defined($rec->{body}) and ($rec->{body} ne ''));
return $md5->hexdigest;
}
__END__
#!/usr/bin/perl
#
# ColdSync Mail conduit
#
# $Id: send-mail,v 1.7 2001/03/16 03:47:53 arensb Exp $
#
use strict;
use Palm::Mail;
use ColdSync;
# Default values for headers
%HEADERS = (
"Outbox-name" => "Outbox", # Name of category for outgoing mail
"Inbox-name" => "Inbox", # Name of category for incoming mail
);
my $VERSION = (qw( $Revision: 1.0 $ ))[1]; # Conduit version
StartConduit("sync");
my $record;
foreach $record (@{$PDB->{records}})
{
# Skip everything except the Outbox folder
next unless (($PDB->{appinfo}{categories}[$record->{category}]{name}
eq $HEADERS{"Outbox-name"})
or
($PDB->{appinfo}{categories}[$record->{category}]{name}
eq $HEADERS{"Inbox-name"}));
# Delete read records
$PDB->delete_Record($record, 1) if ($record->{is_read});
}
EndConduit;
__END__
listen serial {
device: /dev/pilot;
speed: 57600;
}
pda "My Visor" {
snum: *Visor*;
directory: /home/ioe/.visor;
default;
}
conduit dump {
path: /home/ioe/bin/conduits/send-mail;
type: mail/DATA;
arguments:
Sendmail: /usr/sbin/sendmail;
Signature: /home/ioe/.signature;
My-Address: ioe@bertha.s4u;
DSN: return-receipt;
}
conduit fetch {
path: /home/ioe/bin/conduits/fetch-mail;
type: mail/DATA;
arguments:
Local-Inbox: /var/spool/mail/ioe;
# Truncate-After: 8000;
Inbox-name: Inbox;
}
# conduit sync {
# path: /home/ioe/bin/conduits/delete-mail;
# type: mail/DATA;
# arguments:
# Inbox-name: Inbox;
# Outbox-name: Outbox;
#
# }
conduit fetch {
path: /home/ioe/bin/conduits/add-memo.pl;
type: memo/DATA;
arguments:
Where: /home/ioe/tmp/New-Memos;
Category: Temp;
}
conduit dump {
path: /home/ioe/bin/conduits/memo-text;
type: memo/DATA;
arguments:
Where: /home/ioe/Memos-by-cat;
}
conduit sync {
path: /home/ioe/bin/conduits/sync-time.pl;
type: date/DATA;
}
# Plucker
# conduit fetch {
# path: /home/ioe/bin/conduits/sync-plucker;
# type: Plkr/Data;
# }
conduit sync {
path: /bin/true;
type: psys/smfr;
final;
}