chmod 755 /usr/local/bin/vacation
- Code: Select all
#!/usr/bin/perl
#
# NAME
# vacation - Reply to mail automatically.
#
# SYNOPSIS
# vacation [username]
#
# DESCRIPTION
# Vacation automatically replies to incoming mail.
#
# It is enabled by calling vacation without arguments. The
# program creates a .vacation.msg file in your home directory,
# which contains the message that is automatically sent to all
# senders when vacation is enabled, and starts an editor for
# you to modify the message.
#
# If no .forward file exists in your home directory, it is
# created and will contain a line of the form:
#
# \username, "|/usr/local/bin/vacation username"
#
# This sends one copy of an incoming message to username while
# another copy is piped into vacation.
#
# If a .forward file is present in your home directory and
# it does not contain a line refering to the vacation program,
# a line is appended of the form:
#
# "|/usr/local/bin/vacation username"
#
# This pipes a copy of an incoming message into the
# the vacation program, in addition to the copies
# to users or programs which were already specified in the
# .forward file.
#
# If a .forward file is present in your home directory which
# already contains a line refering to the vacation program,
# you are asked whether you want to disable the vacation
# program. If you answer yes, the line refering to the
# vacation program is removed from the .forward file. If the
# .forward file is empty after removing this line, it is
# removed completely.
#
# Vacation will not respond to automatically generated mails
# (like mails generated by vacation). Vacation will also not
# respond to mail from either postmaster or mailer-daemon.
#
# FILES
# ~/.forward Contains e-mail adresses or programs
# to which mail must be forwarded.
#
# ~/.vacation.msg The reply message.
#
# VERSION
# 1.5 (30 August 2004)
#
# AUTHOR
# Frits Wiarda, e-mail fwiarda(at)fwiarda.com
#
# AUTHORS ORIGINAL VERSION
# Tom Christiansen, e-mail tchrist(at)convex.com
# Larry Wall, e-mail lwall(at)jpl-devvax.jpl.nasa.gov
#
# NOTES
# This script has been tested with Red Hat Linux 8.0. Note that
# for other systems it can be necessary to modify line 1, containing
# a reference to the perl interpreter.
#
# Be sure .forward files are processed on your system. Note that some
# systems refuse to process .forward files that are group writable,
# while the systems default umask makes files group writable.
#
######################################################################
#
# Set parameters.
#
######################################################################
$CMDNAME = "vacation";
$HELP = "Reply to mail automatically.\n\nUsage: vacation [username]\n\nWithout parameters vacation prompts the user for instructions.\n";
$USAGE = "Usage: vacation [username]\n";
######################################################################
#
# Print help message when the option "-?" or "--help" is specified.
#
######################################################################
die "$HELP" if $ARGV[0] eq "-?";
die "$HELP" if $ARGV[0] eq "--help";
######################################################################
#
# Locate various executables.
#
######################################################################
$ed = "/bin/ed";
unless (-x $ed) { $ed = "/usr/bin/ed"; }
unless (-x $ed) { die "$CMDNAME: Can't locate ed\n"; }
$editor = $ENV{"VISUAL"} || $ENV{"EDITOR"};
unless ($editor) {
$editor = "/bin/vi";
unless (-x $editor) { $editor = "/usr/bin/vi"; }
unless (-x $editor) { die "$CMDNAME: Can't locate editor\n"; }
}
$pager = $ENV{"PAGER"};
unless ($pager) {
$pager = "/bin/more";
unless (-x $pager) { $pager = "/usr/bin/more"; }
unless (-x $pager) { $pager = "/bin/pg"; }
unless (-x $pager) { $pager = "/usr/bin/pg"; }
unless (-x $pager) { die "$CMDNAME: Can't locate pager\n"; }
}
$sendmail = "/bin/sendmail";
unless (-x $sendmail) { $sendmail = "/sbin/sendmail"; }
unless (-x $sendmail) { $sendmail = "/usr/sbin/sendmail"; }
unless (-x $sendmail) { $sendmail = "/usr/bin/sendmail"; }
unless (-x $sendmail) { die "$CMDNAME: Can't locate sendmail\n"; }
$vacation = $0;
unless (-x $vacation) { die "$CMDNAME: Can't locate own executable\n"; }
######################################################################
#
# Determine the user.
#
######################################################################
$user = $ENV{"USER"} || $ENV{"LOGNAME"} || getlogin || (getpwuid($>))[0];
######################################################################
#
# Without command line arguments we are interactive. With
# an option as command line argument or more then one command
# line argument we print an error message. With a user name as
# the only command line argument we answer mail.
#
######################################################################
if (!@ARGV) {
&interactive();
}
else {
$_ = shift;
if ( /^-/ || @ARGV ) {
die "$USAGE";
}
else {
$user = $_;
&answer;
}
}
######################################################################
#
# Both the interactive and answer subroutines call exit directly. So
# this point is unreachable.
#
######################################################################
die "$CMDNAME: Panic\n";
######################################################################
#
# Answer mode. The vacation program reads mail from the standard
# inut, and uses sendmail to reply to it.
#
######################################################################
sub answer {
# Get the users home directory from the password file.
$home = (getpwnam($user))[7];
die "$CMDNAME: No home directory for user $user\n" unless $home;
# Change to the users home directory.
chdir $home || die "$CMDNAME: Can't chdir to $home\n";
# Set input record seperator to an empty line.
$/ = '';
# Read message into header.
$header = <STDIN>;
# Concatenate headers spread over multiple lines.
$header =~ s/\n\s+/ /gm;
# Do not reply to automatically generated mail.
if ( $header =~ /^Auto-Submitted:/im ) {
exit unless ($header =~ /^Auto-Submitted: no/im );
}
exit if $header =~ /^Precedence: junk/im;
exit if $header =~ /^Precedence: bulk/im;
# Do not reply to mail from mailer-daemon or postmaster.
exit if $header =~ /^From.*mailer-daemon/im;
exit if $header =~ /^From.*postmaster/im;
# Get the sender of the mail.
($replyto) = ($header =~ /^Reply-To:(.*)/im);
$replyto =~ s/^\s*//;
$replyto =~ s/\s*$//;
($replyto) = ($header =~ /^From:(.*)/im) if $replyto eq "";
$replyto =~ s/^\s*//;
$replyto =~ s/\s*$//;
die "$CMDNAME: No \"From:\" or \"Reply-To:\" header\n"
if $replyto eq "";
# Get the subject of the mail.
($subject) = ($header =~ /^Subject:(.*)/im);
$subject =~ s/^\s*//;
$subject =~ s/\s*$//;
$subject = "(No subject)" unless $subject;
# Get reply text. If no .vacation.msg file is present exit,
# without sending anything and without generating an error
# message. (So deleting the message file effectively means
# disabling the vacation program.)
if (open(MSG,".vacation.msg")) {
undef $/;
$msg = <MSG>;
close MSG;
}
else {
exit;
}
# Replace $SUBJECT with real subject text.
$msg =~ s/\$SUBJECT/$subject/gm;
# Send reply using sendmail.
open(MAIL, "|$sendmail -oi -t -f $user") ||
die "$CMDNAME: Can't run sendmail\n";
print MAIL <<EOF;
To: $replyto
Auto-Submitted: auto-replied
Precedence: junk
EOF
print MAIL $msg;
close MAIL;
# Ready.
exit;
}
######################################################################
#
# Internactive mode. The vacation program prompts the user
# for input (whether it should be enabled or disabled, etc.).
#
######################################################################
sub interactive {
# Get the users home directory from the password file.
$home = (getpwnam($user))[7];
die "$CMDNAME: No home directory for user $user\n" unless $home;
# Change to the users home directory.
chdir $home || die "$CMDNAME: Can't chdir to $home\n";
# Check whether vacation has been enabled.
$enabled = 0;
if (-f ".forward")
{
open(FOR, "<.forward") || die "$CMDNAME: Can't open .forward\n";
while($line = <FOR>)
{
if ( $line =~ m|$vacation| )
{
$enabled = 1;
}
}
close FOR;
}
# Ask whether the vacation feature must be disabled. After that
# we are ready and exit.
if ($enabled) {
print "The vacation feature is enabled.\n";
print "\n";
if (&yorn("Would you like to disable the vacation feature? ")) {
&disable;
}
else {
print "Ok, vacation feature NOT disabled.\n";
}
exit;
}
# Vacation feature is disabled. Start dialog to enable it.
# After that we are ready and exit.
print <<EOF;
This program can be used to answer your mail automatically
when you go away on vacation.
EOF
for (;;) {
if (-f ".vacation.msg") {
print "You already have a message file in ~/.vacation.msg.\n";
$see = &yorn("Would you like to see it? ");
system $pager, ".vacation.msg" if $see;
print "\n" if $see;
$edit = &yorn("Would you like to edit it? ");
}
else {
&make_default;
print <<EOF;
I've created a default vacation message in ~/.vacation.msg. This
message will be automatically returned to anyone sending you mail while
you're out.
You will now enter your favorite editor ($editor)
to edit the messasge to your own tastes. Remember that the first
line shall start with "Subject: ", and that the second line shall
be empty.
EOF
$| = 1;
print "Press return to continue. ";
<STDIN>;
$edit = 1;
}
last unless $edit;
system $editor, ".vacation.msg";
last;
}
if (&yorn("Would you like to enable the vacation feature now? ")) {
&enable;
}
else {
print "Ok, vacation feature NOT enabled.\n";
}
exit;
}
######################################################################
#
# Enable the vacation feature. If no .forward file exists one is
# created. If a .forward file exists, a line enabling the vacation
# program is appended to it.
#
######################################################################
sub enable {
if (-f ".forward")
{
open(FOR, ">>.forward") ||
die "$CMDNAME: Can't open .forward\n";
print FOR "\"|$vacation $user\"\n";
close FOR;
}
else
{
open(FOR, ">.forward") ||
die "$CMDNAME: Can't create .forward\n";
print FOR "\\$user, \"|$vacation $user\"\n";
close FOR;
}
print <<EOF;
Ok, vacation feature ENABLED. Please remember to turn it off when
you get back from vacation. Bon voyage!
EOF
}
######################################################################
#
# Disable the vacation feature. The line enabling the vacation
# program is deleted from the .forward file.
#
######################################################################
sub disable {
open(FOR, "|$ed -s .forward") ||
die "$CMDNAME: Can't open pipe to ed .forward\n";
print FOR "g|$vacation|d\nw\nq\n";
close FOR;
if (-z ".forward") {
unlink(".forward");
}
print "Back to normal reception of mail.\n";
}
######################################################################
#
# A default .vacation.msg file is created.
#
######################################################################
sub make_default {
return if $edit;
open(MSG, ">.vacation.msg") ||
die "$CMDNAME: Can't create .vacation.msg\n";
print MSG <<EOF;
Subject: I am away from my mail
I will not be reading my mail for a while. Your mail regarding
$SUBJECT will be read when I return.
EOF
close MSG;
}
######################################################################
#
# Ask a question and read an answer being y(es) or n(o).
#
######################################################################
sub yorn {
local($answer);
for (;;) {
print $_[0];
$answer = <STDIN>;
last if $answer =~ /^[yn]/i;
print "Please answer \"yes\" or \"no\" (\"y\" or \"n\")\n";
}
print "\n";
$answer =~ /^y/i;
}
