1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#!/usr/bin/perl
# pop -- retrieve (new) messages via POP3
use strict;
use warnings;
use Net::POP3;
use POSIX;
use Term::ReadKey;
use Sys::Hostname;
# Flush STDERR
select STDERR; $|++; select STDOUT;
# Process arguments
if (@ARGV != 2) {
print STDERR "usage: $0 mbox mbox.i\n";
exit 1;
}
# Get UIDs of existing messages
my ($mbox, $index, @existing_uids);
if (-e $ARGV[1]) {
open $index, '<', $ARGV[1] or die "Could not open $ARGV[1]: $!";
local $/ = ''; # paragraph mode
while (<$index>) {
push @existing_uids, $1 if /^M-UID: (.*)$/m;
}
close $index;
}
# Open mbox and index files for appending
open $mbox, '>>', $ARGV[0] or die "Could not open $ARGV[0]: $!";
open $index, '>>', $ARGV[1] or die "Could not open $ARGV[1]: $!";
# Get POP3 server, username and password
my $server = 'pop3.mailbox.org';
my $ssl = 1;
my $timeout = 5;
my $username = 'john@ankarstrom.se';
my $password;
if (not $password) {
print 'Enter password: ';
ReadMode 'noecho';
chomp($password = ReadLine(0));
print "\n";
ReadMode 0;
}
# Connect to POP3 server
my $pop = Net::POP3->new($server, SSL => $ssl, Timeout => $timeout)
or die "Could not connect to POP3 server $server: $!\n";
$pop->login($username, $password) or die "Could not log into server\n";
# Retrieve ids and uids of all messages
my @ids = sort { $a <=> $b } keys %{$pop->list};
my %uids = %{$pop->uidl};
# Handle SIGINT
my $sigint = 0;
$SIG{INT} = sub {
print STDERR "\nSafely ending retrieval...\n";
$sigint = 1;
};
# Append new messages to mbox and index files
chomp(my $date = asctime(localtime(time)));
my $offset = 0;
my $i = 0;
for my $id (@ids) {
next if grep { $_ eq $uids{$id} } @existing_uids;
print STDERR "\r$id/$ids[-1]";
my @msg;
{
local $/ = "\r\n";
chomp(@msg = @{$pop->get($id)});
}
# Make From_ line
my ($from, $from_alt);
my $j = 0; # index of empty line before message body
for (@msg) {
last if /^$/;
$j++;
$from = $1 if /^From: (.*)$/;
$from_alt = $1 if /^from: (.*)$/;
}
$from = $from_alt if $from_alt and not $from;
$from = $1 if $from and $from =~ /^.* <(.*?@.*?)>$/;
$from = 'MAILER-DAEMON@' . hostname if not $from;
my $from_ = "From $from $date";
# Calculate message length
my ($head_length, $body_length, $message_length);
$head_length += length($_)+1 for (@msg[0..$j-1]);
$body_length += length($_)+1 for (@msg[$j..$#msg]);
$message_length = length($from_) + 1 + $head_length + $body_length;
# Append message to mbox and index files
local $" = "\n";
print $mbox <<MBOX;
$from_
@msg[0..$j-1]
@msg[$j..$#msg]
MBOX
print $index <<INDEX;
$from_
M-Offset: $offset
M-Length: $message_length
M-Status: 00
M-UID: $uids{$id}
@msg[0..$j-1]
INDEX
exit 130 if $sigint;
# Set offset for next message
$offset += $message_length + 1;
}
print STDERR "\n";
close $index;
close $mbox;
$pop->quit;
|