source: trunk/athena/bin/mitmailutils/mitmailappend.pl @ 23913

Revision 23913, 4.4 KB checked in by andersk, 15 years ago (diff)
In mitmailutils: * Replace test for EXCHANGE.MIT.EDU with test for *EXCHANGE*.
Line 
1#!/usr/bin/perl -w
2
3# $Id: mitmailappend.pl,v 1.1 2004-09-03 20:44:43 rbasch Exp $
4
5# Append a message to an IMAP folder.
6
7use strict;
8use warnings FATAL => 'all';
9use Cyrus::IMAP;
10use Getopt::Long;
11
12sub usage(;$);
13sub read_file($);
14sub send_command(@);
15sub close_and_errorout($);
16sub close_connection();
17sub errorout($);
18
19my $prog = $0;
20
21sub usage(;$) {
22    print STDERR "$prog: $_[0]\n" if ($_[0] && $_[0] ne "help");
23    print STDERR <<EOF;
24Usage: $prog [<options>]
25  Options:
26    --debug                turn on debugging
27    --file=<path>          read message from <path> instead of standard input
28    --help                 print this usage information
29    --host=<name>          query host <name> instead of default POBOX server
30    --mailbox=<name>       access mailbox <name> instead of INBOX
31    --no-create            do not create the target mailbox automatically
32EOF
33    exit 1;
34}
35
36# Parse the command line arguments.
37use vars qw($opt_debug $opt_file $opt_host $opt_mailbox $opt_no_create);
38
39GetOptions("debug",
40           "file=s",
41           "help" => \&usage,
42           "host=s",
43           "mailbox=s",
44           "no-create") || usage;
45
46usage unless @ARGV == 0;
47
48$opt_mailbox = "INBOX" unless $opt_mailbox;
49
50# By default we read the message from standard input.
51$opt_file = "-" unless $opt_file;
52
53my $username = $ENV{'ATHENA_USER'} || $ENV{'USER'} || getlogin || (getpwuid($<))[0] ||
54    errorout "Cannot determine user name";
55
56unless ($opt_host) {
57    $opt_host = (split(" ", `hesinfo $username pobox`))[1] ||
58        errorout "Cannot find Post Office server for $username";
59}
60errorout "Exchange accounts are not supported yet. Try http://owa.mit.edu/." if $opt_host =~ /EXCHANGE/;
61
62# Read the entire message file into a string.
63my $msg = read_file($opt_file);
64
65# Convert LF -> CRLF if necessary.
66unless ($msg =~ m/\r\n/os) {
67    print "Converting LF to CRLF...\n" if $opt_debug;
68    $msg =~ s/\n/\r\n/gos;
69}
70
71# Connect to the IMAP server, and authenticate.
72my $client = Cyrus::IMAP->new($opt_host) ||
73    errorout "Cannot connect to IMAP server on $opt_host";
74$client->authenticate(-authz => $username) ||
75    close_and_errorout "Cannot authenticate to $opt_host";
76
77# Try the APPEND command.  If the server returns an error,
78# check for "TRYCREATE" in the response text; this is a hint that
79# the target mailbox does not exist, but that it can be created.
80my ($status, $text) = send_command("APPEND %s %s", $opt_mailbox, $msg);
81if ($status ne 'OK') {
82    if ($text =~ m/\bTRYCREATE\b/io) {
83        close_and_errorout "Mailbox $opt_mailbox does not exist"
84            if $opt_no_create;
85        print "Creating $opt_mailbox\n" if $opt_debug;
86        # send_command will error out if the CREATE fails.
87        send_command("CREATE %s", $opt_mailbox);
88        ($status, $text) = send_command("APPEND %s %s", $opt_mailbox, $msg);
89    }
90    close_and_errorout "IMAP error from $opt_host: $text"
91        if ($status ne 'OK');
92}
93
94# We are done talking to the IMAP server, close down the connection.
95close_connection();
96
97exit 0;
98
99# Read the given file's entire contents, returning it as a scalar.
100sub read_file($) {
101    my $file = $_[0];
102    local $/ = undef;
103    open(FILE, $file) || errorout "Cannot open $file: $!";
104    my $contents = <FILE>;
105    close(FILE);
106    return $contents;
107}
108
109# Subroutine to send a command to the IMAP server, and wait for the
110# response.  If the response status indicates failure (i.e. is not
111# "OK"), we error out.
112sub send_command(@) {
113    my ($fmt, @args) = @_;
114    printf("Sending: $fmt\n", @args) if $opt_debug;
115    my ($status, $text) = $client->send('', '', $fmt, @args);
116    errorout "Premature end-of-file on IMAP connection to $opt_host"
117        if $status eq 'EOF';
118    print "Response: status $status, text $text\n" if $opt_debug;
119    return ($status, $text) if wantarray;
120    close_and_errorout "IMAP error from $opt_host: $text"
121        if $status ne 'OK';
122}
123
124# Close the connection to the IMAP server, and error out.
125sub close_and_errorout($) {
126    close_connection();
127    errorout $_[0];
128}
129
130# Logout from the IMAP server, and close the connection.
131sub close_connection() {
132    $client->send('', '', "LOGOUT");
133    # Set the client reference to undef, so that perl invokes the
134    # destructor, which closes the connection.  Note that if we invoke
135    # the destructor explicitly here, then perl will still invoke it
136    # again when the program exits, thus touching memory which has
137    # already been freed.
138    $client = undef;
139}
140
141sub errorout($) {
142    print STDERR "$prog: $_[0]\n";
143    exit 1;
144}
Note: See TracBrowser for help on using the repository browser.