mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
new module 32_mailcheck.pm
git-svn-id: https://svn.fhem.de/fhem/trunk@3894 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
18c5fb9123
commit
4b3f5267fe
@ -1,4 +1,5 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
- feature: new module 32_mailcheck.pm (by justme1968)
|
||||
- feature: TCM: new commands added
|
||||
- bugfix: TCM: TCM_ReadAnswer(): response error corrected
|
||||
- feature: readingsGroup: new attribute nolinks
|
||||
|
412
fhem/FHEM/32_mailcheck.pm
Executable file
412
fhem/FHEM/32_mailcheck.pm
Executable file
@ -0,0 +1,412 @@
|
||||
|
||||
# $Id$
|
||||
|
||||
# basic idea from https://github.com/justinribeiro/idlemailcheck
|
||||
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Mail::IMAPClient;
|
||||
use IO::Socket::SSL;
|
||||
use IO::File;
|
||||
use IO::Handle;
|
||||
|
||||
sub
|
||||
mailcheck_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{ReadFn} = "mailcheck_Read";
|
||||
|
||||
$hash->{DefFn} = "mailcheck_Define";
|
||||
$hash->{NotifyFn} = "mailcheck_Notify";
|
||||
$hash->{UndefFn} = "mailcheck_Undefine";
|
||||
#$hash->{SetFn} = "mailcheck_Set";
|
||||
$hash->{GetFn} = "mailcheck_Get";
|
||||
$hash->{AttrFn} = "mailcheck_Attr";
|
||||
$hash->{AttrList} = "debug:1 ".
|
||||
"delete_message:1 ".
|
||||
"disable:1 ".
|
||||
"intervall ".
|
||||
"logfile ".
|
||||
$readingFnAttributes;
|
||||
}
|
||||
|
||||
#####################################
|
||||
|
||||
sub
|
||||
mailcheck_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
return "Usage: define <name> mailcheck host user password [folder]" if(@a < 5);
|
||||
|
||||
my $name = $a[0];
|
||||
|
||||
my $host = $a[2];
|
||||
my $user = $a[3];
|
||||
my $password = $a[4];
|
||||
my $folder = $a[5];
|
||||
|
||||
$hash->{tag} = undef;
|
||||
|
||||
$hash->{NAME} = $name;
|
||||
|
||||
$hash->{Host} = $host;
|
||||
$hash->{User} = $user;
|
||||
$hash->{helper}{PASS} = $password;
|
||||
|
||||
$hash->{Folder} = "INBOX";
|
||||
$hash->{Folder} = $folder if( $folder );
|
||||
|
||||
if( $hash->{STATE} eq "???" ) {
|
||||
$hash->{STATE} = "Initialized";
|
||||
} elsif( $hash->{STATE} ne "???" ) {
|
||||
mailcheck_Disconnect($hash);
|
||||
mailcheck_Connect($hash);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Notify($$)
|
||||
{
|
||||
my ($hash,$dev) = @_;
|
||||
|
||||
if( grep(m/^INITIALIZED$/, @{$dev->{CHANGED}}) ) {
|
||||
delete $hash->{NotifyFn};
|
||||
|
||||
mailcheck_Connect($hash);
|
||||
}
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Connect($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return undef if( AttrVal($name, "disable", 0 ) == 1 );
|
||||
|
||||
my $socket = IO::Socket::SSL->new(
|
||||
PeerAddr => $hash->{Host},
|
||||
PeerPort => 993, #AttrVal($name, "port", 993).
|
||||
);
|
||||
|
||||
if($socket) {
|
||||
$hash->{STATE} = "Connected";
|
||||
$hash->{LAST_CONNECT} = FmtDateTime( gettimeofday() );
|
||||
|
||||
$hash->{FD} = $socket->fileno();
|
||||
$hash->{CD} = $socket; # sysread / close won't work on fileno
|
||||
$hash->{CONNECTS}++;
|
||||
$selectlist{$name} = $hash;
|
||||
Log3 $name, 3, "$name: connected to $hash->{Host}";
|
||||
|
||||
my $client = Mail::IMAPClient->new(
|
||||
Socket => $socket,
|
||||
KeepAlive => 'true',
|
||||
User => $hash->{User},
|
||||
Password => $hash->{helper}{PASS},
|
||||
);
|
||||
|
||||
$client->Debug(AttrVal($name, "debug", 0)) if( $client );
|
||||
$client->Debug_fh($hash->{FH}) if( $client && defined($hash->{FH}) );
|
||||
|
||||
if( $client && $client->IsConnected && $client->IsAuthenticated ) {
|
||||
$hash->{STATE} = "Logged in";
|
||||
$hash->{LAST_LOGIN} = FmtDateTime( gettimeofday() );
|
||||
|
||||
$hash->{CLIENT} = $client;
|
||||
Log3 $name, 3, "$name: logged in to $hash->{User}";
|
||||
|
||||
$hash->{HAS_IDLE} = $client->has_capability("IDLE");
|
||||
|
||||
my $intervall = AttrVal($name, "intervall", 0);
|
||||
$intervall = $hash->{HAS_IDLE}?60*10:60*1 if( !$intervall );
|
||||
$hash->{INTERVAL} = $intervall;
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "mailcheck_poll", $hash, 1);
|
||||
|
||||
#if( !$client->has_capability("IDLE") ) {
|
||||
#mailcheck_Disconnect($hash);
|
||||
#$hash->{STATE} = "IDLE not supported";
|
||||
#return undef;
|
||||
#}
|
||||
|
||||
$client->Uid(0);
|
||||
$client->select($hash->{Folder});
|
||||
|
||||
$hash->{tag} = $client->idle;
|
||||
|
||||
} else {
|
||||
mailcheck_Disconnect($hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
sub
|
||||
mailcheck_Disconnect($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
return if( !$hash->{CD} );
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
$client->done if($client && $client->IsAuthenticated );
|
||||
$client->logout if($client && $client->IsConnected);
|
||||
delete $hash->{CLIENT};
|
||||
$hash->{tag} = undef;
|
||||
Log3 $name, 3, "$name: logged out";
|
||||
|
||||
close($hash->{CD}) if($hash->{CD});
|
||||
delete($hash->{FD});
|
||||
delete($hash->{CD});
|
||||
delete($selectlist{$name});
|
||||
$hash->{STATE} = "Disconnected";
|
||||
Log3 $name, 3, "$name: Disconnected";
|
||||
$hash->{LAST_DISCONNECT} = FmtDateTime( gettimeofday() );
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Undefine($$)
|
||||
{
|
||||
my ($hash, $arg) = @_;
|
||||
|
||||
mailcheck_Disconnect($hash);
|
||||
close( $hash->{FH} );
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Set($$@)
|
||||
{
|
||||
my ($hash, $name, $cmd) = @_;
|
||||
|
||||
my $list = "";
|
||||
return "Unknown argument $cmd, choose one of $list";
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_poll($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "mailcheck_poll", $hash, 1);
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
if( $client && $client->IsConnected && $client->IsAuthenticated ) {
|
||||
$client->done;
|
||||
$client->select($hash->{Folder});
|
||||
$hash->{tag} = $client->idle;
|
||||
$hash->{LAST_POLL} = FmtDateTime( gettimeofday() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sub
|
||||
mailcheck_Get($$@)
|
||||
{
|
||||
my ($hash, $name, $cmd) = @_;
|
||||
|
||||
my $list = "folders:noArg update:noArg";
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
if( $cmd eq "folders" ) {
|
||||
if( $client && $client->IsConnected && $client->IsAuthenticated ) {
|
||||
$client->done;
|
||||
my @folders = $client->folders;
|
||||
$hash->{tag} = $client->idle;
|
||||
return join( "\n", @folders );
|
||||
}
|
||||
return "not connected";
|
||||
} elsif( $cmd eq "update" ) {
|
||||
mailcheck_poll($hash);
|
||||
return undef;
|
||||
}
|
||||
|
||||
return "Unknown argument $cmd, choose one of $list";
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Attr($$$)
|
||||
{
|
||||
my ($cmd, $name, $attrName, $attrVal) = @_;
|
||||
|
||||
my $orig = $attrVal;
|
||||
$attrVal = int($attrVal) if($attrName eq "intervall");
|
||||
$attrVal = 60 if($attrName eq "intervall" && $attrVal < 60 && $attrVal != 0);
|
||||
|
||||
if( $attrName eq "debug" ) {
|
||||
$attrVal = 1 if($attrVal);
|
||||
|
||||
my $hash = $defs{$name};
|
||||
my $client = $hash->{CLIENT};
|
||||
$client->Debug($attrVal) if( $client );
|
||||
} elsif( $attrName eq "logfile" ) {
|
||||
my $hash = $defs{$name};
|
||||
|
||||
close( $hash->{FH} );
|
||||
delete $hash->{FH};
|
||||
delete $hash->{currentlogfile};
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
my @t = localtime;
|
||||
my $f = ResolveDateWildcards($attrVal, @t);
|
||||
my $fh = new IO::File ">>$f";
|
||||
if( defined($fh) ) {
|
||||
Log3 $name, 3, "$name: logging to $f";
|
||||
|
||||
$fh->autoflush(1);
|
||||
|
||||
$hash->{FH} = $fh;
|
||||
$hash->{currentlogfile} = $f;
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
$client->Debug_fh($fh) if( $client );
|
||||
} else {
|
||||
Log3 $name, 3, "$name: can't open log file $f";
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
$client->Debug_fh(*STDERR) if( $client );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( $cmd eq "set" ) {
|
||||
if( $orig ne $attrVal ) {
|
||||
$attr{$name}{$attrName} = $attrVal;
|
||||
return $attrName ." set to ". $attrVal;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sub
|
||||
mailcheck_Read($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $client = $hash->{CLIENT};
|
||||
|
||||
my $ret = $client->idle_data();
|
||||
#Log3 $name, 4, Dumper $ret;
|
||||
|
||||
if( !defined($ret) || !$ret ) {
|
||||
$hash->{tag} = undef;
|
||||
$ret = $client->done;
|
||||
}
|
||||
|
||||
foreach my $resp (@$ret) {
|
||||
$resp =~ s/\015?\012$//;
|
||||
if ( $resp =~ /^\*\s+(\d+)\s+(EXISTS)\b/ ) {
|
||||
$resp =~ s/\D//g;
|
||||
|
||||
$client->done;
|
||||
|
||||
my $msg_count = $client->unseen_count||0;
|
||||
if ($msg_count > 0) {
|
||||
my $from = $client->get_header($resp, "From");
|
||||
$from =~ s/<[^>]*>//g; #strip the email, only display the sender's name
|
||||
|
||||
my $subject = $client->get_header($resp, "Subject");
|
||||
|
||||
readingsSingleUpdate($hash, "Subject", $subject, 1 );
|
||||
|
||||
$client->delete_message( $resp ) if( AttrVal($name, "delete_message", 0) == 1 );
|
||||
}
|
||||
|
||||
$client->idle;
|
||||
|
||||
} elsif ( $resp =~ /^\*\s+(BYE)/ ) {
|
||||
mailcheck_Disconnect($hash);
|
||||
mailcheck_Connect($hash);
|
||||
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
$hash->{tag} ||= $client->idle;
|
||||
|
||||
unless ( $client->IsConnected ) {
|
||||
mailcheck_Disconnect($hash);
|
||||
mailcheck_Connect($hash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
=begin html
|
||||
|
||||
<a name="mailcheck"></a>
|
||||
<h3>mailcheck</h3>
|
||||
<ul>
|
||||
Watches a mailbox with imap idle.<br><br>
|
||||
|
||||
Notes:
|
||||
<ul>
|
||||
<li>Mail::IMAPClient and IO::Socket::SSL hast to be installed on the FHEM host.</li>
|
||||
<li>Probably only works reliably if no other mail programm is marking messages as read at the same time.</li>
|
||||
</ul><br>
|
||||
|
||||
<a name="mailcheck_Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> mailcheck <host> <user> [<folder>]</code><br>
|
||||
<br>
|
||||
|
||||
Defines a mailcheck device that waits for new messages and triggers an event with the mail subject.<br><br>
|
||||
|
||||
Examples:
|
||||
<ul>
|
||||
<code>define mailcheck mailcheck imap.mail.me.com x.y@me.com</code><br>
|
||||
</ul>
|
||||
</ul><br>
|
||||
|
||||
<a name="mailcheck_Readings"></a>
|
||||
<b>Readings</b>
|
||||
<ul>
|
||||
<li>Subject</br>
|
||||
the subject of the last mail received</li>
|
||||
</ul><br>
|
||||
|
||||
<a name="mailcheck_Set"></a>
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
<li>update<br>
|
||||
trigger an update</li>
|
||||
<li>folders<br>
|
||||
list available folders</li>
|
||||
</ul><br>
|
||||
|
||||
<a name="mailcheck_Attr"></a>
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li>delete_message<br>
|
||||
1 -> delete message after Subject reading is created</li>
|
||||
<li>intervall<br>
|
||||
the intervall in seconds used to trigger an update on the connection.
|
||||
if idle is supported the defailt is 600, without idle support the default is 60. the minimum is 60.</li><br>
|
||||
<li>debug<br>
|
||||
1 -> enables debug output. default target is stdout.</li>
|
||||
<li>logfile<br>
|
||||
set the target for debug messages if debug is enabled.</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
=cut
|
@ -85,6 +85,7 @@ FHEM/30_HUEBridge.pm justme1968 http://forum.fhem.de Sonstige
|
||||
FHEM/31_HUEDevice.pm justme1968 http://forum.fhem.de Sonstige Systeme
|
||||
FHEM/31_LightScene.pm justme1968 http://forum.fhem.de Automatisierung
|
||||
FHEM/32_SYSSTAT.pm justme1968 http://forum.fhem.de Unterstützende Dienste
|
||||
FHEM/32_mailcheck.pm justme1968 http://forum.fhem.de Automatisierung
|
||||
FHEM/33_readingsGroup.pm justme1968 http://forum.fhem.de Frontends
|
||||
FHEM/32_speedtest.pm justme1968 http://forum.fhem.de Sonstiges
|
||||
FHEM/34_panStamp.pm justme1968 http://forum.fhem.de Sonstiges Systeme
|
||||
|
Loading…
Reference in New Issue
Block a user