Merge pull request #654 from TV4Fun/emailonly
Add 'emailonly' client to send status emails without needing a DDNS service
This commit is contained in:
commit
d1068bede1
5 changed files with 127 additions and 2 deletions
|
@ -41,6 +41,8 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
|||
* The second and subsequent lines in a multi-line log message are now prefixed
|
||||
with a `|` character.
|
||||
[#676](https://github.com/ddclient/ddclient/pull/676)
|
||||
* `emailonly`: New `protocol` option that simply emails you when your IP
|
||||
address changes. [#654](https://github.com/ddclient/ddclient/pull/654)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ handwritten_tests = \
|
|||
t/builtinfw_query.pl \
|
||||
t/get_ip_from_if.pl \
|
||||
t/geturl_connectivity.pl \
|
||||
t/interval_expired.pl \
|
||||
t/is-and-extract-ipv4.pl \
|
||||
t/is-and-extract-ipv6.pl \
|
||||
t/is-and-extract-ipv6-global.pl \
|
||||
|
|
|
@ -391,3 +391,9 @@ ssl=yes # use ssl-support. Works with
|
|||
# password=ddns_password
|
||||
# redirect=2
|
||||
# example.com
|
||||
|
||||
##
|
||||
## Email Only
|
||||
##
|
||||
# protocol=emailonly
|
||||
# host.example.com
|
||||
|
|
69
ddclient.in
69
ddclient.in
|
@ -104,7 +104,7 @@ my $programd = $0;
|
|||
$programd =~ s%^.*/%%;
|
||||
my $program = $programd;
|
||||
$program =~ s/d$//;
|
||||
my $now = time;
|
||||
our $now = time;
|
||||
my $hostname = hostname();
|
||||
|
||||
# subst_var(subst, default) returns subst unless it looks like @foo@ in which case it returns
|
||||
|
@ -140,7 +140,8 @@ $ENV{'PATH'} = (exists($ENV{PATH}) ? "$ENV{PATH}:" : "") . "/sbin:/usr/sbin:/bin
|
|||
|
||||
our %globals;
|
||||
our %config;
|
||||
my ($result, %cache);
|
||||
our %cache;
|
||||
my $result;
|
||||
my $saved_cache;
|
||||
my %saved_opt;
|
||||
my $daemon;
|
||||
|
@ -1066,6 +1067,18 @@ my %services = (
|
|||
%{$variables{'service-common-defaults'}},
|
||||
},
|
||||
},
|
||||
'emailonly' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_emailonly_update,
|
||||
'examples' => \&nic_emailonly_examples,
|
||||
'variables' => {
|
||||
%{$variables{'service-common-defaults'}},
|
||||
'login' => undef,
|
||||
'password' => undef,
|
||||
# Change default to never re-notify if IP address has not changed.
|
||||
'max-interval' => setv(T_DELAY, 0, 0, 'inf', 0),
|
||||
},
|
||||
},
|
||||
);
|
||||
# Delete undefined variables to make it easier to cancel previously defined variables.
|
||||
for my $svc (values(%services)) {
|
||||
|
@ -2465,6 +2478,8 @@ sub interval {
|
|||
$value = $1 * 60*60;
|
||||
} elsif ($value =~ /^(\d+)(days|d)/i) {
|
||||
$value = $1 * 60*60*24;
|
||||
} elsif ($value =~ qr/^(?:inf(?:init[ye])?|indefinite(?:ly)?|never|forever|always)$/i) {
|
||||
$value = 'inf';
|
||||
} elsif ($value !~ /^\d+$/) {
|
||||
$value = undef;
|
||||
}
|
||||
|
@ -2473,6 +2488,7 @@ sub interval {
|
|||
sub interval_expired {
|
||||
my ($host, $time, $interval) = @_;
|
||||
|
||||
return 0 if ($config{$host}{$interval} // 0) == 'inf';
|
||||
return 1 if !exists $cache{$host};
|
||||
return 1 if !exists $cache{$host}{$time} || !$cache{$host}{$time};
|
||||
return 1 if !exists $config{$host}{$interval} || !$config{$host}{$interval};
|
||||
|
@ -8076,6 +8092,55 @@ sub nic_infomaniak_update {
|
|||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_emailonly_update
|
||||
##
|
||||
## Written by Joel Croteau
|
||||
##
|
||||
## Do not update Dynamic DNS, only send status emails. Use if you do
|
||||
## not have a DDNS host, but still want to get emails when your IP
|
||||
## address changes. Note that you must set the "mail" config option
|
||||
## and configure sendmail for this to have an effect. At least one
|
||||
## host must be specified; the host names are mentioned in the email.
|
||||
######################################################################
|
||||
sub nic_emailonly_update {
|
||||
debug("\nnic_emailonly_update -------------------");
|
||||
# Note: This is logged after $config{$_}{'max-interval'] even if the IP address hasn't changed,
|
||||
# so it is best to avoid phrasing like, "IP address has changed."
|
||||
logmsg(email => 1, join("\n", 'Host IP addresses:', map({
|
||||
my $ipv4 = delete($config{$_}{'wantipv4'});
|
||||
my $ipv6 = delete($config{$_}{'wantipv6'});
|
||||
$config{$_}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$_}{'status-ipv6'} = 'good' if $ipv6;
|
||||
$config{$_}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$_}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$_}{'mtime'} = $now;
|
||||
sprintf('%30s %s', $_, join(' ', grep(defined($_), $ipv4, $ipv6)));
|
||||
} @_)));
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_emailonly_examples
|
||||
######################################################################
|
||||
sub nic_emailonly_examples {
|
||||
return <<"EoEXAMPLE";
|
||||
o 'emailonly'
|
||||
|
||||
The 'emailonly' protocol is a dummy protocol that will send status emails but
|
||||
not actually issue any dynamic DNS updates. You can use this if you don\'t
|
||||
have a DDNS host, but still want to get emails when your IP address changes.
|
||||
For this to have an effect, you must set the 'mail' config option, have
|
||||
sendmail properly configured on your machine, and specify at least one dummy
|
||||
hostname.
|
||||
|
||||
Example ${program}.conf file entries:
|
||||
## single host update
|
||||
mail=me\@example.com
|
||||
protocol=emailonly
|
||||
host.example.com
|
||||
EoEXAMPLE
|
||||
}
|
||||
|
||||
# Execute main() if this file is run as a script or run via PAR (https://metacpan.org/pod/PAR),
|
||||
# otherwise do nothing. This "modulino" pattern makes it possible to import this file as a module
|
||||
# and test its functions directly; there's no need for test-only command-line arguments or stdout
|
||||
|
|
51
t/interval_expired.pl
Normal file
51
t/interval_expired.pl
Normal file
|
@ -0,0 +1,51 @@
|
|||
use Test::More;
|
||||
SKIP: { eval { require Test::Warnings; } or skip($@, 1); }
|
||||
eval { require 'ddclient'; } or BAIL_OUT($@);
|
||||
|
||||
my $h = 't/interval_expired.pl';
|
||||
|
||||
my $default_now = 1000000000;
|
||||
|
||||
my @test_cases = (
|
||||
{
|
||||
interval => 'inf',
|
||||
want => 0,
|
||||
},
|
||||
{
|
||||
now => 'inf',
|
||||
interval => 'inf',
|
||||
want => 0,
|
||||
},
|
||||
{
|
||||
cache => '-inf',
|
||||
interval => 'inf',
|
||||
want => 0,
|
||||
},
|
||||
{
|
||||
cache => undef, # Falsy cache value.
|
||||
interval => 'inf',
|
||||
want => 0,
|
||||
},
|
||||
{
|
||||
now => 0,
|
||||
cache => 0, # Different kind of falsy cache value.
|
||||
interval => 'inf',
|
||||
want => 0,
|
||||
},
|
||||
);
|
||||
|
||||
for my $tc (@test_cases) {
|
||||
$tc->{now} //= $default_now;
|
||||
# For convenience, $tc->{cache} is an offset from $tc->{now}, not an absolute time..
|
||||
my $cachetime = $tc->{now} + $tc->{cache} if defined($tc->{cache});
|
||||
$ddclient::config{$h} = {'interval' => $tc->{interval}};
|
||||
%ddclient::config if 0; # suppress spurious warning "Name used only once: possible typo"
|
||||
$ddclient::cache{$h} = {'cached-time' => $cachetime} if defined($cachetime);
|
||||
%ddclient::cache if 0; # suppress spurious warning "Name used only once: possible typo"
|
||||
$ddclient::now = $tc->{now};
|
||||
$ddclient::now if 0; # suppress spurious warning "Name used only once: possible typo"
|
||||
my $desc = "now=$tc->{now}, cache=${\($cachetime // 'undef')}, interval=$tc->{interval}";
|
||||
is(ddclient::interval_expired($h, 'cached-time', 'interval'), $tc->{want}, $desc);
|
||||
}
|
||||
|
||||
done_testing();
|
Loading…
Reference in a new issue