]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/Fetchmail.pm
1 package PMG
::Fetchmail
;
12 use PMG
::ClusterConfig
;
14 my $inotify_file_id = 'fetchmailrc';
15 my $config_filename = '/etc/pmg/fetchmailrc';
16 my $config_link_filename = '/etc/fetchmailrc';
18 my $fetchmail_default_id = 'fetchmail_default';
19 my $fetchmail_default_filename = '/etc/default/fetchmail';
21 sub read_fetchmail_default
{
22 my ($filename, $fh) = @_;
25 while (defined(my $line = <$fh>)) {
26 if ($line =~ m/^START_DAEMON=yes\s*$/) {
35 sub write_fetchmail_default
{
36 my ($filename, $fh, $enable) = @_;
38 open (my $orgfh, "<", $filename);
40 my $wrote_start_daemon = 0;
42 my $write_start_daemon_line = sub {
44 return if $wrote_start_daemon; # only once
45 $wrote_start_daemon = 1;
48 print $fh "START_DAEMON=yes\n";
50 print $fh "START_DAEMON=no\n";
54 if (defined($orgfh)) {
55 while (defined(my $line = <$orgfh>)) {
56 if ($line =~ m/^#?START_DAEMON=.*$/) {
57 $write_start_daemon_line->();
63 $write_start_daemon_line->();
67 PVE
::INotify
::register_file
(
68 $fetchmail_default_id, $fetchmail_default_filename,
69 \
&read_fetchmail_default
,
70 \
&write_fetchmail_default
,
72 always_call_parser
=> 1);
74 my $set_fetchmail_defaults = sub {
77 $item->{protocol
} //= 'pop3';
78 $item->{interval
} //= 1;
79 $item->{enable
} //= 0;
82 if ($item->{protocol
} eq 'pop3') {
88 } elsif ($item->{protocol
} eq 'imap') {
95 die "unknown fetchmail protocol '$item->{protocol}'\n";
102 sub read_fetchmail_conf
{
103 my ($filename, $fh) = @_;
109 # scan for proxmox marker - skip non proxmox lines
110 while (defined(my $line = <$fh>)) {
111 last if $line =~ m/^\#\s+proxmox\s+settings.*$/;
118 my $get_next_token = sub {
121 while ($data =~ /\G("([^"]*)"|\S+|)(?:\s|$)/g) {
122 my ($token, $string) = ($1, $2);
124 $string =~ s/\\x([0-9A-Fa-f]{2})/chr(hex($1))/eg
126 return wantarray ?
($token, $string) : $token;
130 $linenr = $fh->input_line_number();
131 } while (defined($data));
136 my $get_token_argument = sub {
137 my ($token, $string) = $get_next_token->();
138 die "line $linenr: missing token arguemnt\n" if !$token;
139 return $string // $token;
142 my $finalize_item = sub {
144 $cfg->{$item->{id
}} = $item;
148 while (my ($token, $string) = $get_next_token->()) {
149 last if !defined($token);
150 if ($token eq 'poll' || $token eq 'skip') {
151 $finalize_item->($item) if defined($item);
152 my $id = $get_token_argument->();
153 $item = { id
=> $id };
154 $item->{enable
} = $token eq 'poll' ?
1 : 0;
158 die "line $linenr: unexpected token '$token'\n"
161 if ($token eq 'user') {
162 $item->{user
} = $get_token_argument->();
163 } elsif ($token eq 'via') {
164 $item->{server
} = $get_token_argument->();
165 } elsif ($token eq 'pass') {
166 $item->{pass
} = $get_token_argument->();
167 } elsif ($token eq 'to') {
168 $item->{target
} = $get_token_argument->();
169 } elsif ($token eq 'protocol') {
170 $item->{protocol
} = $get_token_argument->();
171 } elsif ($token eq 'port') {
172 $item->{port
} = $get_token_argument->();
173 } elsif ($token eq 'interval') {
174 $item->{interval
} = $get_token_argument->();
175 } elsif ($token eq 'ssl' || $token eq 'keep' ||
176 $token eq 'dropdelivered') {
179 die "line $linenr: unexpected token '$token' inside entry '$item->{id}'\n";
182 $finalize_item->($item) if defined($item);
188 sub write_fetchmail_conf
{
189 my ($filename, $fh, $fmcfg) = @_;
193 # Note: we correctly quote data here to make fetchmailrc.tt simpler
197 foreach my $id (keys %$fmcfg) {
198 my $org = $fmcfg->{$id};
199 my $item = { id
=> $id };
201 foreach my $k (keys %$org) {
203 $v =~ s/([^A-Za-z0-9\:\@\-\._~])/sprintf "\\x%02x",ord($1)/eg;
206 $set_fetchmail_defaults->($item);
207 my $options = [ 'dropdelivered' ];
208 push @$options, 'ssl' if $item->{ssl
};
209 push @$options, 'keep' if $item->{keep
};
210 $item->{options
} = join(' ', @$options);
211 $data->{$id} = $item;
216 my $pmgcfg = PMG
::Config-
>new();
217 my $vars = $pmgcfg->get_template_vars();
218 $vars->{fetchmail_users
} = $data;
220 my $tt = PMG
::Config
::get_template_toolkit
();
221 $tt->process('fetchmailrc.tt', $vars, \
$raw) ||
222 die $tt->error() . "\n";
224 my (undef, undef, $uid, $gid) = getpwnam('fetchmail');
225 chown($uid, $gid, $fh) if defined($uid) && defined($gid);
228 PVE
::Tools
::safe_print
($filename, $fh, $raw);
230 update_fetchmail_default
($entry_count);
233 sub update_fetchmail_default
{
236 my $cinfo = PMG
::ClusterConfig-
>new();
238 my $is_enabled = PVE
::INotify
::read_file
('fetchmail_default');
239 my $role = $cinfo->{local}->{type
} // '-';
240 if (($role eq '-') || ($role eq 'master')) {
241 if (!!$enable != !!$is_enabled) {
242 PVE
::INotify
::write_file
('fetchmail_default', $enable);
243 PMG
::Utils
::service_cmd
('fetchmail', 'restart');
245 if (! -e
$config_link_filename) {
246 symlink ($config_filename, $config_link_filename);
250 PVE
::INotify
::write_file
('fetchmail_default', 0);
252 if (-e
$config_link_filename) {
253 unlink $config_link_filename;
258 PVE
::INotify
::register_file
(
259 $inotify_file_id, $config_filename,
260 \
&read_fetchmail_conf
,
261 \
&write_fetchmail_conf
,
263 always_call_parser
=> 1);