Beim Verschicken von Emails wird das Kommando $sendmail durch Lx-Offices Template...
[kivitendo-erp.git] / SL / Mailer.pm
1 #=====================================================================
2 # LX-Office ERP
3 # Copyright (C) 2004
4 # Based on SQL-Ledger Version 2.1.9
5 # Web http://www.lx-office.org
6 #
7 #=====================================================================
8 # SQL-Ledger Accounting
9 # Copyright (C) 2001
10 #
11 #  Author: Dieter Simader
12 #   Email: dsimader@sql-ledger.org
13 #     Web: http://www.sql-ledger.org
14 #
15 # Contributors:
16 #
17 # This program is free software; you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation; either version 2 of the License, or
20 # (at your option) any later version.
21 #
22 # This program is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 # GNU General Public License for more details.
26 # You should have received a copy of the GNU General Public License
27 # along with this program; if not, write to the Free Software
28 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #======================================================================
30
31 package Mailer;
32
33 use SL::Common;
34 use SL::Template;
35
36 sub new {
37   $main::lxdebug->enter_sub();
38
39   my ($type) = @_;
40   my $self = {};
41
42   $main::lxdebug->leave_sub();
43
44   bless $self, $type;
45 }
46
47 sub mime_quote_text {
48   $main::lxdebug->enter_sub();
49
50   my ($self, $text, $chars_left) = @_;
51
52   my $q_start = "=?$self->{charset}?Q?";
53   my $l_start = length($q_start);
54
55   my $new_text = "$q_start";
56   $chars_left -= $l_start;
57
58   for (my $i = 0; $i < length($text); $i++) {
59     my $char = ord(substr($text, $i, 1));
60
61     if (($char < 32) || ($char > 127) ||
62         ($char == ord('?')) || ($char == ord('_'))) {
63       if ($chars_left < 5) {
64         $new_text .= "?=\n $q_start";
65         $chars_left = 75 - $l_start;
66       }
67
68       $new_text .= sprintf("=%02X", $char);
69       $chars_left -= 3;
70
71     } else {
72       $char = ord('_') if ($char == ord(' '));
73       if ($chars_left < 5) {
74         $new_text .= "?=\n $q_start";
75         $chars_left = 75 - $l_start;
76       }
77
78       $new_text .= chr($char);
79       $chars_left--;
80     }
81   }
82
83   $new_text .= "?=";
84
85   $main::lxdebug->leave_sub();
86
87   return $new_text;
88 }
89
90 sub send {
91   $main::lxdebug->enter_sub();
92
93   my ($self) = @_;
94
95   local (*IN, *OUT);
96
97   my $boundary =  time();
98   $boundary    =  "LxOffice-$self->{version}-$boundary";
99   my $domain   =  $self->{from};
100   $domain      =~ s/(.*?\@|>)//g;
101   my $msgid    =  "$boundary\@$domain";
102
103   my $form     =  $main::form;
104   my $myconfig =  \%main::myconfig;
105
106   my $email    =  $myconfig->{email};
107   $email       =~ s/[^\w\.\-\+=@]//ig;
108
109   $form->{myconfig_email} = $email;
110
111   my $template =  PlainTextTemplate->new(undef, $form, $myconfig);
112   my $sendmail =  $template->parse_block($main::sendmail);
113
114   $self->{charset} = Common::DEFAULT_CHARSET unless $self->{charset};
115
116   if (!open(OUT, $sendmail)) {
117     $main::lxdebug->leave_sub();
118     return "$sendmail : $!";
119   }
120
121   $self->{contenttype} = "text/plain" unless $self->{contenttype};
122
123   my ($cc, $bcc);
124   $cc  = "Cc: $self->{cc}\n"   if $self->{cc};
125   $bcc = "Bcc: $self->{bcc}\n" if $self->{bcc};
126
127   foreach my $item (qw(to cc bcc)) {
128     $self->{$item} =~ s/\&lt;/</g;
129     $self->{$item} =~ s/\$<\$/</g;
130     $self->{$item} =~ s/\&gt;/>/g;
131     $self->{$item} =~ s/\$>\$/>/g;
132   }
133
134   my $subject = $self->mime_quote_text($self->{subject}, 60);
135
136   print OUT qq|From: $self->{from}
137 To: $self->{to}
138 ${cc}${bcc}Subject: $subject
139 Message-ID: <$msgid>
140 X-Mailer: Lx-Office $self->{version}
141 MIME-Version: 1.0
142 |;
143
144   if ($self->{attachments}) {
145     print OUT qq|Content-Type: multipart/mixed; boundary="$boundary"
146
147 |;
148     if ($self->{message}) {
149       print OUT qq|--${boundary}
150 Content-Type: $self->{contenttype}; charset="$self->{charset}"
151
152 $self->{message}
153
154 |;
155     }
156
157     foreach my $attachment (@{ $self->{attachments} }) {
158
159       my $filename;
160
161       if (ref($attachment) eq "HASH") {
162         $filename = $attachment->{"name"};
163         $attachment = $attachment->{"filename"};
164       } else {
165         $filename = $attachment;
166         # strip path
167         $filename =~ s/(.*\/|\Q$self->{fileid}\E)//g;
168       }
169
170       my $application =
171         ($attachment =~ /(^\w+$)|\.(html|text|txt|sql)$/)
172         ? "text"
173         : "application";
174
175       open(IN, $attachment);
176       if ($?) {
177         close(OUT);
178         $main::lxdebug->leave_sub();
179         return "$attachment : $!";
180       }
181
182       print OUT qq|--${boundary}
183 Content-Type: $application/$self->{format}; name="$filename"; charset="$self->{charset}"
184 Content-Transfer-Encoding: BASE64
185 Content-Disposition: attachment; filename="$filename"\n\n|;
186
187       my $msg = "";
188       while (<IN>) {
189         ;
190         $msg .= $_;
191       }
192       print OUT &encode_base64($msg);
193
194       close(IN);
195
196     }
197     print OUT qq|--${boundary}--\n|;
198
199   } else {
200     print OUT qq|Content-Type: $self->{contenttype}; charset="$self->{charset}"
201
202 $self->{message}
203 |;
204   }
205
206   close(OUT);
207
208   $main::lxdebug->leave_sub();
209
210   return "";
211 }
212
213 sub encode_base64 ($;$) {
214   $main::lxdebug->enter_sub();
215
216   # this code is from the MIME-Base64-2.12 package
217   # Copyright 1995-1999,2001 Gisle Aas <gisle@ActiveState.com>
218
219   my $res = "";
220   my $eol = $_[1];
221   $eol = "\n" unless defined $eol;
222   pos($_[0]) = 0;    # ensure start at the beginning
223
224   $res = join '', map(pack('u', $_) =~ /^.(\S*)/, ($_[0] =~ /(.{1,45})/gs));
225
226   $res =~ tr|` -_|AA-Za-z0-9+/|;    # `# help emacs
227                                     # fix padding at the end
228   my $padding = (3 - length($_[0]) % 3) % 3;
229   $res =~ s/.{$padding}$/'=' x $padding/e if $padding;
230
231   # break encoded string into lines of no more than 60 characters each
232   if (length $eol) {
233     $res =~ s/(.{1,60})/$1$eol/g;
234   }
235
236   $main::lxdebug->leave_sub();
237
238   return $res;
239 }
240
241 1;
242