1#!--PERL-- 2# -*- indent-tabs-mode: nil; -*- 3# vim:ft=perl:et:sw=4 4# $Id$ 5 6# Sympa - SYsteme de Multi-Postage Automatique 7# 8# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel 9# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 10# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites 11# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER 12# Copyright 2017, 2018, 2019 The Sympa Community. See the AUTHORS.md file at 13# the top-level directory of this distribution and at 14# <https://github.com/sympa-community/sympa.git>. 15# 16# This program is free software; you can redistribute it and/or modify 17# it under the terms of the GNU General Public License as published by 18# the Free Software Foundation; either version 2 of the License, or 19# (at your option) any later version. 20# 21# This program is distributed in the hope that it will be useful, 22# but WITHOUT ANY WARRANTY; without even the implied warranty of 23# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24# GNU General Public License for more details. 25# 26# You should have received a copy of the GNU General Public License 27# along with this program. If not, see <http://www.gnu.org/licenses/>. 28 29## Worl Wide Sympa is a front-end to Sympa Mailing Lists Manager 30## Copyright Comite Reseau des Universites 31 32## Patch 2001.07.24 by nablaphi <nablaphi@bigfoot.com> 33## Change the Getopt::Std to Getopt::Long 34 35use lib split(/:/, $ENV{SYMPALIB} || ''), '--modulesdir--'; 36use strict; 37use warnings; 38use English qw(-no_match_vars); 39use Getopt::Long; 40use Pod::Usage; 41use POSIX qw(); 42 43use Conf; 44use Sympa::Constants; 45use Sympa::Crash; # Show traceback. 46use Sympa::DatabaseManager; 47use Sympa::Log; 48use Sympa::Process; 49use Sympa::Spindle::ProcessBounce; 50use Sympa::Spool::Listmaster; 51 52my $process = Sympa::Process->instance; 53$process->init(pidname => 'bounced'); 54 55## Check options 56my %options; 57unless ( 58 GetOptions( 59 \%main::options, 'config|f=s', 'debug|d', 'help|h', 60 'log_level=s', 'foreground|F', 'version|v', 61 ) 62) { 63 pod2usage(-exitval => 1, -output => \*STDERR); 64} 65if ($main::options{'help'}) { 66 pod2usage(0); 67} elsif ($main::options{'version'}) { 68 printf "Sympa %s\n", Sympa::Constants::VERSION; 69 exit 0; 70} 71$Conf::sympa_config = $main::options{config}; 72 73if ($main::options{'debug'}) { 74 $main::options{'log_level'} = 2 unless $main::options{'log_level'}; 75 $main::options{'foreground'} = 1; 76} 77 78my $log = Sympa::Log->instance; 79$log->{log_to_stderr} = 'all' if $main::options{'foreground'}; 80 81# Load sympa.conf 82unless (Conf::load()) { 83 die sprintf 84 "Unable to load sympa configuration, file %s has errors.\n", 85 Conf::get_sympa_conf(); 86} 87 88# Check database connectivity 89unless (Sympa::DatabaseManager->instance) { 90 die sprintf 91 "Database %s defined in sympa.conf has not the right structure or is unreachable.\n", 92 $Conf::Conf{'db_name'}; 93} 94 95# Put ourselves in background if not in debug mode. 96unless ($main::options{'foreground'}) { 97 $process->daemonize; 98} 99 100# Create and write the PID file. 101$process->write_pid(initial => 1); 102# If process is running in foreground, don't write STDERR to a dedicated file. 103unless ($main::options{foreground}) { 104 $process->direct_stderr_to_file; 105} 106 107if ($main::options{'log_level'}) { 108 $log->{level} = $main::options{'log_level'}; 109 $log->syslog( 110 'info', 111 'Configuration file read, log level set using options: %s', 112 $main::options{'log_level'} 113 ); 114} else { 115 $log->{level} = $Conf::Conf{'log_level'}; 116 $log->syslog( 117 'info', 118 'Configuration file read, default log level %s', 119 $Conf::Conf{'log_level'} 120 ); 121} 122 123my $log_facility = $Conf::Conf{'log_facility'} || $Conf::Conf{'syslog'}; 124$log->openlog($log_facility, $Conf::Conf{'log_socket_type'}); 125 126## Set the User ID & Group ID for the process 127$GID = $EGID = (getgrnam(Sympa::Constants::GROUP))[2]; 128$UID = $EUID = (getpwnam(Sympa::Constants::USER))[2]; 129 130## Required on FreeBSD to change ALL IDs 131## (effective UID + real UID + saved UID) 132POSIX::setuid((getpwnam(Sympa::Constants::USER))[2]); 133POSIX::setgid((getgrnam(Sympa::Constants::GROUP))[2]); 134 135## Check if the UID has correctly been set (useful on OS X) 136unless (($GID == (getgrnam(Sympa::Constants::GROUP))[2]) 137 && ($UID == (getpwnam(Sympa::Constants::USER))[2])) { 138 die 139 "Failed to change process user ID and group ID. Note that on some OS Perl scripts can't change their real UID. In such circumstances Sympa should be run via sudo.\n"; 140} 141 142## Sets the UMASK 143umask(oct($Conf::Conf{'umask'})); 144 145## Change to list root 146unless (chdir($Conf::Conf{'home'})) { 147 die sprintf "Unable to change directory to %s: %s", $Conf::Conf{'home'}, 148 $!; 149} 150 151$log->syslog('notice', 'Bounced %s Started', Sympa::Constants::VERSION()); 152 153my $spindle = Sympa::Spindle::ProcessBounce->new; 154 155## Catch signals, in order to exit cleanly, whenever possible. 156$SIG{'TERM'} = 'sigterm'; 157$SIG{'INT'} = 'sigterm'; 158 159while (not $spindle->{finish}) { 160 $spindle->spin; 161 last if $spindle->{finish}; 162 163 # If the spool was empty, sleep for a while. 164 sleep $Conf::Conf{'sleep'}; 165} 166 167# Purge grouped notifications 168Sympa::Spool::Listmaster->instance->flush(purge => 1); 169 170$log->syslog('notice', 'Bounced exited normally due to signal'); 171$process->remove_pid(final => 1); 172 173exit(0); 174 175# When we catch signal, just change the value of the loop variable. 176sub sigterm { 177 my ($sig) = @_; 178 $log->syslog('notice', 179 'Signal %s received, still processing current task', $sig); 180 $spindle->{finish} = $sig; 181} 182 183## copy the bounce to the appropriate filename 184# Moved: Use Sympa::Tracking::store(). 185#sub store_bounce; 186 187# Moved to Sympa::Spindle::ProcessBounce::_twist(). 188#sub process_message; 189 190# Old name: Bounce::rfc1891(). 191# Moved to Sympa::Spindle::ProcessBounce::_parse_dsn(). 192#sub _parse_dsn; 193 194# Moved to Sympa::Spindle::ProcessBounce::_parse_multipart_report(). 195#sub _parse_multipart_report; 196 197# Moved to Sympa::Spindle::ProcessBounce::_decode_utf_8_addr_xtext(). 198#sub _decode_utf_8_addr_xtext; 199 200# Moved to %Sympa::Spindle::ProcessBounce::equiv. 201#my %equiv; 202 203# Old name: Bounce::corrige(). 204# Moved to Sympa::Spindle::ProcessBounce::_corrige(). 205#sub _corrige; 206 207# Old name: Bounce::anabounce(). 208# Moved to Sympa::Spindle::ProcessBounce::_anabounce(). 209#sub _anabounce; 210 211# Moved to Sympa::Spindle::ProcessBounce::_canonicalize_status(). 212#sub _canonicalize_status; 213 214# Moved: Now a subroutine of Sympa::Tracking::store(). 215#sub _update_subscriber_bounce_history; 216 217# If bounce can't be handled correctly, saves it to the "bad" subdirectory of 218# the bounce spool. 219#DEPRECATED. Use Sympa::Spool::Bounce::quarantine(). 220# sub quarantine; 221 222#DEPRECATED. Use Sympa::Spool::Bounce::remove(). 223# sub remove; 224 225__END__ 226 227=encoding utf-8 228 229=head1 NAME 230 231bounced, bounced.pl - Mailing List Bounce Processing Daemon for Sympa 232 233=head1 SYNOPSIS 234 235C<bounced.pl> S<[ C<--foreground> ]> S<[ C<--debug> ]> 236 237=head1 DESCRIPTION 238 239Bounced is a program which scans permanently the bounce spool and 240processes bounces (non-delivery messages), looking or bad addresses. 241Bouncing addresses are tagged in database ; last bounce is kept for 242each bouncing address. 243 244List owners will be able to access information about the bounces 245via WWSympa after they have been processed by bounced. 246 247=head1 OPTIONS 248 249These programs follow the usual GNU command line syntax, 250with long options starting with two dashes (C<-->). A summary of 251options is included below. 252 253=over 5 254 255=item C<-F>, C<--foreground> 256 257Do not detach TTY. 258 259=item C<-f>, C<--config=>I<file> 260 261Force bounced to use an alternative configuration file instead 262of F<--CONFIG-->. 263 264=item C<-d>, C<--debug> 265 266Run the program in a debug mode. 267 268=item C<-h>, C<--help> 269 270Print this help message. 271 272=item C<--log_level=>I<level> 273 274Sets daemon log level. 275 276=back 277 278=head1 FILES 279 280F<--CONFIG--> Sympa configuration file. 281 282F<$LIBEXECDIR/bouncequeue> bounce spooler, referenced from sendmail alias file 283 284F<$SPOOLDIR/bounce> incoming bounces directory 285 286F<$PIDDIR/bounced.pid> this file contains the process ID 287of F<bounced.pl>. 288 289=head1 MORE DOCUMENTATION 290 291The full documentation can be 292found in L<https://sympa-community.github.io/manual/>. 293 294The mailing lists (with web archives) can be accessed at 295L<https://listes.renater.fr/sympa/lists/informatique/sympa>. 296 297=head1 HISTORY 298 299This program was originally written by: 300 301=over 4 302 303=item Serge Aumont 304 305ComitE<233> RE<233>seau des UniversitE<233>s 306 307=item Olivier SalaE<252>n 308 309ComitE<233> RE<233>seau des UniversitE<233>s 310 311=back 312 313This manual page was initially written by 314JE<233>rE<244>me Marant <jerome.marant@IDEALX.org> 315for the Debian GNU/Linux system. 316 317=head1 LICENSE 318 319You may distribute this software under the terms of the GNU General 320Public License Version 2. For more details see F<README> file. 321 322Permission is granted to copy, distribute and/or modify this document 323under the terms of the GNU Free Documentation License, Version 1.1 or 324any later version published by the Free Software Foundation; with no 325Invariant Sections, no Front-Cover Texts and no Back-Cover Texts. A 326copy of the license can be found under 327L<http://www.gnu.org/licenses/fdl.html>. 328 329=head1 BUGS 330 331Report bugs to Sympa bug tracker. 332See L<http://www.sympa.org/tracking>. 333 334=head1 SEE ALSO 335 336L<sympa_msg(8)>, L<wwsympa(8)>, L<mhonarc(1)>, L<sympa.conf(5)>. 337 338L<Sympa::Spindle::ProcessBounce>. 339 340=cut 341