1 |
slords |
1.1 |
diff -Nur -x '*.orig' -x '*.rej' smeserver-qpsmtpd-1.2.1/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime mezzanine_patched_smeserver-qpsmtpd-1.2.1/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime |
2 |
|
|
--- smeserver-qpsmtpd-1.2.1/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime 1970-01-01 10:00:00.000000000 +1000 |
3 |
|
|
+++ mezzanine_patched_smeserver-qpsmtpd-1.2.1/root/etc/e-smith/templates/var/service/qpsmtpd/config/plugins/62tnef2mime 2006-11-22 16:11:58.296578417 +1100 |
4 |
|
|
@@ -0,0 +1,6 @@ |
5 |
|
|
+{ |
6 |
|
|
+ return "# tnef to mime conversion disabled" |
7 |
|
|
+ unless ($smtpd{tnef2mime} eq "enabled"); |
8 |
|
|
+ return "tnef2mime"; |
9 |
|
|
+} |
10 |
|
|
+ |
11 |
|
|
diff -Nur -x '*.orig' -x '*.rej' smeserver-qpsmtpd-1.2.1/root/usr/share/qpsmtpd/plugins/tnef2mime mezzanine_patched_smeserver-qpsmtpd-1.2.1/root/usr/share/qpsmtpd/plugins/tnef2mime |
12 |
|
|
--- smeserver-qpsmtpd-1.2.1/root/usr/share/qpsmtpd/plugins/tnef2mime 1970-01-01 10:00:00.000000000 +1000 |
13 |
|
|
+++ mezzanine_patched_smeserver-qpsmtpd-1.2.1/root/usr/share/qpsmtpd/plugins/tnef2mime 2006-11-22 16:12:46.971100622 +1100 |
14 |
|
|
@@ -0,0 +1,160 @@ |
15 |
|
|
+#!/usr/bin/perl -wT |
16 |
|
|
+=head1 NAME |
17 |
|
|
+ |
18 |
|
|
+tnef2mime |
19 |
|
|
+ |
20 |
|
|
+=head1 DESCRIPTION |
21 |
|
|
+ |
22 |
|
|
+Plugin that converts ms-tnef attachments (winmail.dat) and uuencoded attachments to MIME. |
23 |
|
|
+ |
24 |
|
|
+perl-Convert-TNEF, perl-IO-stringy, perl-File-MMagic and perl-MIME-tools are required. |
25 |
|
|
+ |
26 |
|
|
+=head1 AUTHOR |
27 |
|
|
+ |
28 |
|
|
+Michael Weinberger, neddix Stuttgart, 2005 |
29 |
|
|
+ |
30 |
|
|
+=head1 LICENSE |
31 |
|
|
+ |
32 |
|
|
+GNU GPL (GNU General Public License) |
33 |
|
|
+ |
34 |
|
|
+ |
35 |
|
|
+=cut |
36 |
|
|
+ |
37 |
|
|
+ |
38 |
|
|
+use MIME::Parser; |
39 |
|
|
+use MIME::Entity; |
40 |
|
|
+use MIME::Head; |
41 |
|
|
+use File::MMagic; |
42 |
|
|
+use Convert::TNEF; |
43 |
|
|
+ |
44 |
|
|
+my $parser; |
45 |
|
|
+my $ent; |
46 |
|
|
+my $tmpdir='/var/spool/qpsmtpd'; |
47 |
|
|
+my $count=0; |
48 |
|
|
+my $foundtnef=0; |
49 |
|
|
+my (@attachments, @blocked, @tnefs); |
50 |
|
|
+ |
51 |
|
|
+ |
52 |
|
|
+sub register { |
53 |
|
|
+ my ($self, $qp, %arg) = @_; |
54 |
|
|
+ $self->register_hook("data_post", "tnef2mime"); |
55 |
|
|
+} |
56 |
|
|
+ |
57 |
|
|
+# for future use |
58 |
|
|
+sub kill_part ($) |
59 |
|
|
+ { |
60 |
|
|
+ my $part=$_; |
61 |
|
|
+ #my $path = defined $part->bodyhandle ? $part->bodyhandle->path : ""; |
62 |
|
|
+ #my $filename = $part->head->recommended_filename || ""; |
63 |
|
|
+ return $part; |
64 |
|
|
+ } |
65 |
|
|
+ |
66 |
|
|
+sub keep_part ($$) |
67 |
|
|
+ { |
68 |
|
|
+ my ($self,$part)=@_; |
69 |
|
|
+ my $mm = new File::MMagic; |
70 |
|
|
+ |
71 |
|
|
+ # when a ms-tnef attachment was sent uuencoded, its MIME type becomes application/octet-stream |
72 |
|
|
+ # after the conversion. Therefore all application/octet-stream attachments are assumed to |
73 |
|
|
+ # be a ms-tnef |
74 |
|
|
+ |
75 |
|
|
+ my $path = $part->bodyhandle ? $part->bodyhandle->path : ""; |
76 |
|
|
+ |
77 |
|
|
+ if( $part->mime_type =~ /ms-tnef/i || $part->mime_type =~ /application\/octet-stream/i ) |
78 |
|
|
+ { |
79 |
|
|
+ # convert tnef attachments and write to files |
80 |
|
|
+ my $tnef = Convert::TNEF->read_ent($part,{output_dir=>$tmpdir,output_to_core=>"NONE"}); |
81 |
|
|
+ |
82 |
|
|
+ # if $tnef is undefined here, the application/octet-stream was not a ms-tnef and we are done. |
83 |
|
|
+ return 1 if( ! defined $tnef ); |
84 |
|
|
+ |
85 |
|
|
+ for ($tnef->attachments) |
86 |
|
|
+ { |
87 |
|
|
+ next if !defined $_->datahandle; |
88 |
|
|
+ my $mimetype = $mm->checktype_filename( $_->datahandle->path ); |
89 |
|
|
+ $attachments[$count] = MIME::Entity->build( |
90 |
|
|
+ Path=>$_->datahandle->path, |
91 |
|
|
+ Filename=>$_->longname, |
92 |
|
|
+ Encoding=>"base64", |
93 |
|
|
+ Type=>$mimetype ); |
94 |
|
|
+ $self->log(LOGDEBUG, |
95 |
|
|
+ sprintf "converted attachment #%i: %s (%s, %ld bytes)", $count+1, $_->longname, $mimetype, $_->size ); |
96 |
|
|
+ $count++; |
97 |
|
|
+ } |
98 |
|
|
+ push( @tnefs, $tnef ); # remind for cleanup |
99 |
|
|
+ $foundtnef=1; |
100 |
|
|
+ return 0; |
101 |
|
|
+ } |
102 |
|
|
+ return 1; |
103 |
|
|
+ } |
104 |
|
|
+ |
105 |
|
|
+ |
106 |
|
|
+sub tnef2mime ( $$ ) |
107 |
|
|
+ { |
108 |
|
|
+ my ($self, $transaction) = @_; |
109 |
|
|
+ # new Parser Object |
110 |
|
|
+ $parser = new MIME::Parser; |
111 |
|
|
+ # temp output directory |
112 |
|
|
+ $parser->output_under( $tmpdir ); |
113 |
|
|
+ $parser->extract_uuencode(1); |
114 |
|
|
+ |
115 |
|
|
+ # read message body |
116 |
|
|
+ open BFN, $transaction->body_filename(); |
117 |
|
|
+ $ent = $parser->parse(\*BFN); |
118 |
|
|
+ my @keep = grep { keep_part($self, $_) } $ent->parts; # @keep now holds all non-tnef attachments |
119 |
|
|
+ close BFN; |
120 |
|
|
+ |
121 |
|
|
+ my $founduu = $ent->parts && !$transaction->header->get('MIME-Version'); |
122 |
|
|
+ |
123 |
|
|
+ if( $foundtnef || $founduu ) |
124 |
|
|
+ { |
125 |
|
|
+ my @allatt; |
126 |
|
|
+ @allatt = map { kill_part($_) } ( @keep, @attachments ); |
127 |
|
|
+ $ent->parts(\@allatt); |
128 |
|
|
+ # if message is a multipart type, but has MIME version tag, then add |
129 |
|
|
+ # MIME version. PHP imap_fetchstructure() depends on that! |
130 |
|
|
+ my $xac; |
131 |
|
|
+ if( $founduu ) |
132 |
|
|
+ { |
133 |
|
|
+ $transaction->header->add('MIME-Version', "1.0" ); |
134 |
|
|
+ $xac = "UUENCODE -> MIME"; |
135 |
|
|
+ $self->log(LOGDEBUG, "uuencoded attachment converted to MIME" ); |
136 |
|
|
+ } |
137 |
|
|
+ # delete the X-MS-TNEF-Correlator header line |
138 |
|
|
+ if( $foundtnef ) |
139 |
|
|
+ { |
140 |
|
|
+ $xac .= ( defined $xac ? ", " : "" ) . "MS-TNEF -> MIME"; |
141 |
|
|
+ $transaction->header->delete('X-MS-TNEF-Correlator' ); |
142 |
|
|
+ } |
143 |
|
|
+ # add own X header |
144 |
|
|
+ if( defined $xac ) |
145 |
|
|
+ { |
146 |
|
|
+ $transaction->header->add('X-TNEF2MIME-Plugin', $xac ); |
147 |
|
|
+ } |
148 |
|
|
+ # write converted message body |
149 |
|
|
+ open BFN, ">" . $transaction->body_filename(); |
150 |
|
|
+ $ent->print(\*BFN); |
151 |
|
|
+ close BFN; |
152 |
|
|
+ } |
153 |
|
|
+ |
154 |
|
|
+ # cleaning up |
155 |
|
|
+ for( my $i=0; $i<@tnefs; $i++ ) |
156 |
|
|
+ { |
157 |
|
|
+ $tnefs[$i]->purge(); |
158 |
|
|
+ } |
159 |
|
|
+ |
160 |
|
|
+ my $output_dir = $parser->output_dir; |
161 |
|
|
+ |
162 |
|
|
+ opendir( DIR, $output_dir ) or die "Could not open temporary output dir $output_dir: $!\n"; |
163 |
|
|
+ while( defined( my $file = readdir( DIR ) ) ) |
164 |
|
|
+ { |
165 |
|
|
+ next if $file =~ /^\.\.?$/; |
166 |
|
|
+ $file =~ s/(^.*$)//; |
167 |
|
|
+ $file = $1; |
168 |
|
|
+ unlink( "$output_dir/$file" ); |
169 |
|
|
+ } |
170 |
|
|
+ closedir( DIR ); |
171 |
|
|
+ rmdir( $output_dir ); |
172 |
|
|
+ |
173 |
|
|
+ return DECLINED; |
174 |
|
|
+ } |