mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 18:59:33 +00:00
MSG: Replace file and mail related code with delegates
MSGFile: Assimilate file related code from 75_MSG to make it standalone, without requiring MSG device MSGMail: Assimilate mail related code from 75_MSG to make it standalone, without requiring MSG device git-svn-id: https://svn.fhem.de/fhem/trunk@8546 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
9f18e906a1
commit
6835b464c3
@ -1,5 +1,10 @@
|
||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
||||
# Do not insert empty lines here, update check depends on it.
|
||||
- change: MSG: Replace file and mail related code with delegates
|
||||
- change: MSGFile: Assimilate file related code from 75_MSG
|
||||
to make it standalone, without requiring MSG device
|
||||
- change: MSGMail: Assimilate mail related code from 75_MSG
|
||||
to make it standalone, without requiring MSG device
|
||||
- bugfix: MSG: Determine which SSL implementation to use for sending mail
|
||||
(required for libnet-3.06)
|
||||
- change: MilightDevice/MilightBridge: Fixes, features, changes (by MarkusM)
|
||||
|
@ -4,6 +4,9 @@
|
||||
#
|
||||
# History:
|
||||
#
|
||||
# 2015-05-09: Move mail related code to MSGMail,
|
||||
# and file related code to MSGFile,
|
||||
# rewrite to use delegates for compatibility
|
||||
# 2015-05-07: Determine which SSL implementation to use
|
||||
# 2015-05-06: Tidy up code for restructuring
|
||||
# 2015-05-05: Remove dependency on Switch
|
||||
@ -13,19 +16,12 @@ package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use MIME::Lite;
|
||||
#use Net::SMTP::SSL;
|
||||
|
||||
use Net::SMTP; # libnet-3.06 has SSL included, so we need to check the version
|
||||
|
||||
my %sets = (
|
||||
"send" => "MSG",
|
||||
"write" => "MSG",
|
||||
);
|
||||
|
||||
my $MSGMail_SSL = 0;
|
||||
my $MSGMail_SMTP = 0;
|
||||
|
||||
sub MSG_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
@ -33,54 +29,6 @@ sub MSG_Initialize($)
|
||||
$hash->{SetFn} = "MSG_Set";
|
||||
$hash->{DefFn} = "MSG_Define";
|
||||
$hash->{AttrList} = "loglevel:0,1,2,3,4,5,6";
|
||||
|
||||
my $name = "MSG";
|
||||
|
||||
# check version of libnet - if < 3.00, try to load Net::SMTP::SSL
|
||||
$MSGMail_SMTP = $Net::SMTP::VERSION;
|
||||
if ($Net::SMTP::VERSION >= 3)
|
||||
{
|
||||
$MSGMail_SSL = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
eval "use Net::SMTP::SSL";
|
||||
if ($@)
|
||||
{
|
||||
Log 0, $@ if($@);
|
||||
$MSGMail_SSL = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
$MSGMail_SSL = 1;
|
||||
}
|
||||
}
|
||||
Log 2, "$name: SSL is ".(($MSGMail_SSL) ? ("available, provided by Net::SMTP".(($MSGMail_SMTP<3.00)?"::SSL":"")):"not available");
|
||||
}
|
||||
|
||||
sub MSGMail_conn($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my ($name) = $hash->{NAME};
|
||||
|
||||
my $smtphost = AttrVal($name, "smtphost", "");
|
||||
my $smtpport = AttrVal($name, "smtpport", "465"); # 465 is the default port
|
||||
|
||||
if ($MSGMail_SSL)
|
||||
{
|
||||
if ($MSGMail_SMTP < 3.00)
|
||||
{
|
||||
Log3 $name, 3, "$name: try to connect with Net::SMTP::SSL";
|
||||
return Net::SMTP::SSL->new($smtphost, Port => $smtpport);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log3 $name, 3, "$name: try to connect with Net::SMTP";
|
||||
return Net::SMTP->new(Host=>$smtphost, Port=>$smtpport, SSL=>1);
|
||||
}
|
||||
}
|
||||
Log3 $name, 0, "$name: SSL not available. Connection will fail";
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub MSG_Set($@)
|
||||
@ -106,126 +54,14 @@ sub MSG_Set($@)
|
||||
{
|
||||
return "TYPE for $defs{$a[1]} not defined";
|
||||
}
|
||||
|
||||
####################################################################################################
|
||||
##
|
||||
## M S G F i l e
|
||||
##
|
||||
####################################################################################################
|
||||
elsif ($defs{ $a[1] }{TYPE} eq "MSGFile")
|
||||
{
|
||||
|
||||
return "No filename specified, use attr <name> filename <filename> $a[1] $defs{$a[1]}{TYPE}"
|
||||
if (!AttrVal($a[1], "filename", ""));
|
||||
|
||||
# open the file, new = delete file before create it
|
||||
# append = add lines to the existing file contents
|
||||
if (AttrVal($a[1], "filemode", "") eq "new")
|
||||
{
|
||||
open(FHEMMSGFILE, ">" . AttrVal($a[1], "filename", ""))
|
||||
|| return "Can not open the file: $!";
|
||||
}
|
||||
else
|
||||
{
|
||||
open(FHEMMSGFILE, ">>" . AttrVal($a[1], "filename", ""))
|
||||
|| return "Can not open the file: $!";
|
||||
}
|
||||
|
||||
# loop thru the stored lines and write them to the file
|
||||
# number of lines are in the Readings / msgcount
|
||||
my $i;
|
||||
if (ReadingsVal($a[1], "msgcount", 0) > 0)
|
||||
{
|
||||
for ($i = 0 ; $i < ReadingsVal($a[1], "msgcount", 0) ; $i++)
|
||||
{
|
||||
print FHEMMSGFILE $data{ $a[1] }{$i}
|
||||
|| return "Can not write to the file: $!";
|
||||
}
|
||||
}
|
||||
|
||||
# close the file and send a message to the log
|
||||
close(FHEMMSGFILE);
|
||||
Log 1, "<MSG> write to File: " . AttrVal($a[1], "filename", "");
|
||||
} # END MSGFile
|
||||
|
||||
####################################################################################################
|
||||
##
|
||||
## M S G M a i l
|
||||
##
|
||||
## We use MAIL::Lite to compose the message, because it works very well at this and
|
||||
## we use Net::SMTP::SSL to connect to the smtp host and manage the authenification,
|
||||
## because MAIL:Lite is not very easy to manage with SSL connections
|
||||
####################################################################################################
|
||||
|
||||
fhem("set $a[1] write");
|
||||
}
|
||||
elsif ($defs{ $a[1] }{TYPE} eq "MSGMail")
|
||||
{
|
||||
# check all required data
|
||||
my $from = AttrVal($a[1], "from", "");
|
||||
return "No <from> address specified, use attr $a[1] from <mail-address>"
|
||||
if (!$from);
|
||||
my $to = AttrVal($a[1], "to", "");
|
||||
return "No <to> address specified, use attr $a[1] to <mail-address>"
|
||||
if (!$to);
|
||||
my $subject = AttrVal($a[1], "subject", "");
|
||||
return "No <subject> specified, use attr $a[1] subject <text>"
|
||||
if (!$subject);
|
||||
my $authfile = AttrVal($a[1], "authfile", "");
|
||||
return "No <authfile> specified, use attr $a[1] authfile <filename>"
|
||||
if (!$authfile);
|
||||
my $smtphost = AttrVal($a[1], "smtphost", "");
|
||||
return "No <smtphost> name specified, use attr $a[1] sntphost <hostname>"
|
||||
if (!$smtphost);
|
||||
my $smtpport = AttrVal($a[1], "smtpport", "465"); # 465 is the default port
|
||||
my $cc = AttrVal($a[1], "cc", ""); # Carbon Copy
|
||||
open(FHEMAUTHFILE, "<" . $authfile)
|
||||
|| return "Can not open authfile $authfile: $!";
|
||||
my @auth = <FHEMAUTHFILE>;
|
||||
close(FHEMAUTHFILE);
|
||||
chomp(@auth);
|
||||
|
||||
# Log 1, "MSG User = <" . @auth[0] . "> Passwort = <" . @auth[1] . ">";
|
||||
|
||||
# compose message
|
||||
my $i;
|
||||
my $mess = "";
|
||||
for ($i = 0 ; $i < ReadingsVal($a[1], "msgcount", 0) ; $i++)
|
||||
{
|
||||
$mess .= $data{ $a[1] }{$i};
|
||||
}
|
||||
|
||||
my $mailmsg = MIME::Lite->new(
|
||||
From => $from,
|
||||
To => $to,
|
||||
Subject => $subject,
|
||||
Type => 'text/plain; charset=UTF-8', #'multipart/mixed', # was 'text/plain'
|
||||
Data => $mess
|
||||
);
|
||||
|
||||
# login to the SMTP Host using SSL and send the message
|
||||
my $smtp;
|
||||
my $smtperrmsg = "SMTP Error: ";
|
||||
|
||||
#$smtp = Net::SMTP::SSL->new($smtphost, Port => $smtpport)
|
||||
$smtp = MSGMail_conn($defs{ $a[1] })
|
||||
or return $smtperrmsg . " Can't connect to host $smtphost";
|
||||
$smtp->auth($auth[0], $auth[1])
|
||||
or return $smtperrmsg . " Can't authenticate: " . $smtp->message();
|
||||
$smtp->mail($from) or return $smtperrmsg . $smtp->message();
|
||||
$smtp->to($to) or return $smtperrmsg . $smtp->message();
|
||||
if ($cc ne '')
|
||||
{
|
||||
Log 1, "CC = $cc";
|
||||
$smtp->cc($cc) or return $smtperrmsg . $smtp->message();
|
||||
}
|
||||
$smtp->data() or return $smtperrmsg . $smtp->message();
|
||||
$smtp->datasend($mailmsg->as_string)
|
||||
or return $smtperrmsg . $smtp->message();
|
||||
$smtp->dataend() or return $smtperrmsg . $smtp->message();
|
||||
$smtp->quit() or return $smtperrmsg . $smtp->message();
|
||||
|
||||
Log 1, "<MSG> send EMail: <$subject>";
|
||||
|
||||
} ###> END MSGMail
|
||||
fhem("set $a[1] send");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "MSG Filetype $defs{$a[1]}{TYPE} unknown";
|
||||
@ -263,16 +99,22 @@ sub MSG_Define($$)
|
||||
<a name="MSG"></a>
|
||||
<h3>MSG</h3>
|
||||
<ul>
|
||||
The MSG device is the backend device for all the message handling (I/O-engine).
|
||||
Under normal conditions only one MSG device is needed to serve multiple frontend
|
||||
message devices like file or email.
|
||||
The MSG device is deprecated.<br><br>
|
||||
It used to be the backend device for I/O-handling of <a href="#MSGMail">MSGMail</a>
|
||||
and <a href="#MSGFile">MSGFile</a> devices.
|
||||
The MSG device can still be used for this purpose, but actually delegates send and
|
||||
write commands to the <a href="#MSGMail">MSGMail</a> and <a href="#MSGFile">MSGFile</a>
|
||||
devices, respectively.<br><br>
|
||||
Before removing a deprecated MSG device from an installation, make sure to change
|
||||
code in user functions, accordingly.
|
||||
<br><br>
|
||||
<a name="MSGdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> MSG </code><br><br>
|
||||
Specifies the MSG device. A single MSG device could serve multiple MSG frontends.
|
||||
But, for special conditions there could be defined more than one MSG device.
|
||||
Specifies the MSG device. This is no longer required since
|
||||
<a href="#MSGFile">MSGFile</a> and <a href="#MSGMail">MSGMail</a>
|
||||
devices provide all necessary functionality.
|
||||
</ul>
|
||||
<br>
|
||||
<a name="MSGset"></a>
|
||||
@ -282,18 +124,12 @@ sub MSG_Define($$)
|
||||
</ul>
|
||||
Notes:
|
||||
<ul>
|
||||
To send the data, both send or write could be used.<br>
|
||||
The devicename is the name of a frontenddevice previously
|
||||
defined. Based on the type of the frontend device, the MSG device
|
||||
will send out the lines of data.
|
||||
To process the data, both 'send' and 'write' can be used.<br>
|
||||
The MSG device will delegate the command to the device specified
|
||||
by 'devicename' and automatically use 'send' for
|
||||
<a href="#MSGMail">MSGMail</a> and 'write' for
|
||||
<a href="#MSGFile">MSGFile</a> devices.
|
||||
<br>
|
||||
Frontend devices are available for:<br>
|
||||
<ul><li><a href="#MSGFile">File</a></li>
|
||||
<li><a href="#MSGMail">EMail with SSL Authentification</a></li></ul>
|
||||
For details about this devices, please review the device-definitions.<br>
|
||||
After sending/writing the data, the data stills exists with the
|
||||
frontend device, MSG do not delete/purge any data, this must be done
|
||||
by the frontend device.
|
||||
<br><br>
|
||||
Examples:
|
||||
<ul>
|
||||
@ -302,12 +138,8 @@ sub MSG_Define($$)
|
||||
</ul>
|
||||
<a name="MSGVattr"></a>
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li><a href="#IODev">IODev</a></li>
|
||||
<li><a href="#dummy">dummy</a></li>
|
||||
<li><a href="#ignore">ignore</a></li>
|
||||
<ul>
|
||||
<li><a href="#loglevel">loglevel</a></li>
|
||||
<li><a href="#eventMap">eventMap</a></li><br>
|
||||
</ul>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
@ -2,15 +2,12 @@
|
||||
# $Id$
|
||||
########################################################
|
||||
#
|
||||
# Created 2012 by rbente
|
||||
#
|
||||
########################################################
|
||||
#
|
||||
# History:
|
||||
#
|
||||
# 2015-05-06: tidy up code for restructuring
|
||||
# 2015-05-05: remove dependency on Switch
|
||||
#
|
||||
# 2015-05-09: Assimilate file related code from 75_MSG
|
||||
# 2015-05-06: Tidy up code for restructuring
|
||||
# 2015-05-05: Remove dependency on Switch
|
||||
# 2012 : Created by rbente
|
||||
#
|
||||
package main;
|
||||
|
||||
@ -19,7 +16,8 @@ use warnings;
|
||||
my %sets = (
|
||||
"add" => "MSGFile",
|
||||
"clear" => "MSGFile",
|
||||
"list" => "MSGFile"
|
||||
"list" => "MSGFile",
|
||||
"write" => "MSGFile"
|
||||
);
|
||||
|
||||
##############################################
|
||||
@ -41,78 +39,6 @@ sub MSGFile_Initialize($)
|
||||
$hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 filename filemode:new,append CR:0,1";
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Set Function
|
||||
# all the data are stored in the global array @data
|
||||
# as counter we use a READING named msgcount
|
||||
##############################################
|
||||
sub MSGFile_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets)
|
||||
if (!defined($sets{ $a[1] }));
|
||||
|
||||
my $name = shift @a;
|
||||
|
||||
return "no set value specified" if (int(@a) < 1);
|
||||
return "Unknown argument ?" if ($a[0] eq "?");
|
||||
my $v = join(" ", @a);
|
||||
|
||||
# we like to add another line of data
|
||||
if ($a[0] eq "add")
|
||||
{
|
||||
# split the line in command and data
|
||||
my $mx = shift @a;
|
||||
my $my = join(" ", @a);
|
||||
# check if we like to have and CR at the end of the line
|
||||
if (AttrVal($name, "CR", "0") eq "1")
|
||||
{
|
||||
$my = $my . "\n";
|
||||
}
|
||||
# get the highest number of lines, store the line in @data and increase
|
||||
# the counter, at the end set the status
|
||||
my $count = $hash->{READINGS}{msgcount}{VAL};
|
||||
$data{$name}{$count} = $my;
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = $count + 1;
|
||||
$hash->{STATE} = "addmsg";
|
||||
|
||||
}
|
||||
# we like to clear our buffer, first clear all lines of @data
|
||||
# and then set the counter to 0 and the status to clear
|
||||
elsif ($a[0] eq "clear")
|
||||
{
|
||||
my $i;
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$data{$name}{$i} = "";
|
||||
}
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = 0;
|
||||
$hash->{STATE} = "clear";
|
||||
|
||||
}
|
||||
# we like to see the buffer
|
||||
elsif ($a[0] eq "list")
|
||||
{
|
||||
my $i;
|
||||
my $mess = "---- Lines of data for $name ----\n";
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$mess .= $data{$name}{$i};
|
||||
}
|
||||
return "$mess---- End of data for $name ----";
|
||||
}
|
||||
|
||||
Log GetLogLevel($name, 2), "messenger set $name $v";
|
||||
|
||||
# set stats
|
||||
# $hash->{CHANGED}[0] = $v;
|
||||
$hash->{READINGS}{state}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{state}{VAL} = $v;
|
||||
return undef;
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Define Function
|
||||
# set the counter to 0
|
||||
@ -155,6 +81,117 @@ sub MSGFile_Undef($$)
|
||||
delete($modules{MSGFile}{defptr}{ $hash->{CODE} }) if ($hash && $hash->{CODE});
|
||||
return undef;
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Set Function
|
||||
# all the data are stored in the global array @data
|
||||
# as counter we use a READING named msgcount
|
||||
##############################################
|
||||
sub MSGFile_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets)
|
||||
if (!defined($sets{ $a[1] }));
|
||||
|
||||
my $name = shift @a;
|
||||
|
||||
return "no set value specified" if (int(@a) < 1);
|
||||
return "Unknown argument ?" if ($a[0] eq "?");
|
||||
my $v = join(" ", @a);
|
||||
|
||||
# we like to add another line of data
|
||||
if ($a[0] eq "add")
|
||||
{
|
||||
# split the line in command and data
|
||||
my $mx = shift @a;
|
||||
my $my = join(" ", @a);
|
||||
|
||||
# check if we like to have and CR at the end of the line
|
||||
if (AttrVal($name, "CR", "0") eq "1")
|
||||
{
|
||||
$my = $my . "\n";
|
||||
}
|
||||
|
||||
# get the highest number of lines, store the line in @data and increase
|
||||
# the counter, at the end set the status
|
||||
my $count = $hash->{READINGS}{msgcount}{VAL};
|
||||
$data{$name}{$count} = $my;
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = $count + 1;
|
||||
$hash->{STATE} = "addmsg";
|
||||
|
||||
}
|
||||
|
||||
# we like to clear our buffer, first clear all lines of @data
|
||||
# and then set the counter to 0 and the status to clear
|
||||
elsif ($a[0] eq "clear")
|
||||
{
|
||||
my $i;
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$data{$name}{$i} = "";
|
||||
}
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = 0;
|
||||
$hash->{STATE} = "clear";
|
||||
|
||||
}
|
||||
|
||||
# we like to see the buffer
|
||||
elsif ($a[0] eq "list")
|
||||
{
|
||||
my $i;
|
||||
my $mess = "---- Lines of data for $name ----\n";
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$mess .= $data{$name}{$i};
|
||||
}
|
||||
return "$mess---- End of data for $name ----";
|
||||
}
|
||||
elsif ($a[0] eq "write")
|
||||
{
|
||||
return "No filename specified, use attr <name> filename <filename> $name $defs{$name}{TYPE}"
|
||||
if (!AttrVal($name, "filename", ""));
|
||||
|
||||
# open the file, new = delete file before create it
|
||||
# append = add lines to the existing file contents
|
||||
if (AttrVal($name, "filemode", "") eq "new")
|
||||
{
|
||||
open(FHEMMSGFILE, ">" . AttrVal($name, "filename", ""))
|
||||
|| return "Can not open the file: $!";
|
||||
}
|
||||
else
|
||||
{
|
||||
open(FHEMMSGFILE, ">>" . AttrVal($name, "filename", ""))
|
||||
|| return "Can not open the file: $!";
|
||||
}
|
||||
|
||||
# loop thru the stored lines and write them to the file
|
||||
# number of lines are in the Readings / msgcount
|
||||
my $i;
|
||||
if (ReadingsVal($name, "msgcount", 0) > 0)
|
||||
{
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
print FHEMMSGFILE $data{ $name }{$i}
|
||||
|| return "Can not write to the file: $!";
|
||||
}
|
||||
}
|
||||
|
||||
# close the file and send a message to the log
|
||||
close(FHEMMSGFILE);
|
||||
Log 1, "<MSG> write to File: " . AttrVal($name, "filename", "");
|
||||
} # END MSGFile
|
||||
|
||||
Log GetLogLevel($name, 2), "messenger set $name $v";
|
||||
|
||||
# set stats
|
||||
# $hash->{CHANGED}[0] = $v;
|
||||
$hash->{READINGS}{state}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{state}{VAL} = $v;
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -163,15 +200,13 @@ sub MSGFile_Undef($$)
|
||||
<a name="MSGFile"></a>
|
||||
<h3>MSGFile</h3>
|
||||
<ul>
|
||||
The MSGFile device is a frontend device for message handling.
|
||||
With a MSGFile device data is written to disk (or other media).
|
||||
Multiple MSGFile devices could be defined.
|
||||
To write the data to disk, a MSG device is necessary.
|
||||
A MSGFile device needs the operating systems rights to write to the filesystem.
|
||||
The MSGFile device is used to write arbitrary data to a file on disk
|
||||
or other media accessable through the filesystem. In order to write to a file,
|
||||
the access rights of the FHEM process to the specified file and path are relevant.
|
||||
To set the rights for a directory, please use OS related commands.
|
||||
<br><br>
|
||||
|
||||
<a name="MSGFileDefine"></a>
|
||||
<a name="MSGFileDefine"></a>
|
||||
<b>Define</b>
|
||||
<ul><br>
|
||||
<code>define <name> MSGFile <filename></code><br><br>
|
||||
@ -186,33 +221,38 @@ sub MSGFile_Undef($$)
|
||||
<a name="MSGFileSet"></a>
|
||||
|
||||
<b>Set</b><br>
|
||||
<ul><code>set <name> add|clear|list [text]</code><br>
|
||||
<ul><code>set <name> add|clear|list|write [text]</code><br>
|
||||
Set is used to manipulate the message buffer of the device. The message
|
||||
buffer is an array of lines of data, stored serial based on the incoming
|
||||
time into the buffer. Lines of data inside the buffer could not be deleted
|
||||
anymore, except of flashing the whole buffer.<br>
|
||||
|
||||
<ul><b>add</b><br> to add lines of data to the message buffer. All data behind
|
||||
"add" will be interpreted as text message. To add a carriage return to the data,
|
||||
please use the CR attribute.
|
||||
</ul>
|
||||
|
||||
<ul><b>clear</b><br> to flash the message buffer and set the line counter to 0.
|
||||
All the lines of data are deleted and the buffer is flushed.</ul>
|
||||
|
||||
<ul><b>list</b><br> to list the message buffer.</ul><br>
|
||||
</ul><br>
|
||||
Examples:
|
||||
<ul>
|
||||
<code>set myFile add Dies ist Textzeile 1</code><br>
|
||||
<code>set myFile add Dies ist Textzeile 2</code><br>
|
||||
<code>set myFile clear</code><br><br>
|
||||
Full working example to write two lines of data to a file:<br>
|
||||
<code>define myMsg MSG</code><br>
|
||||
<code>define myFile MSGFile /tmp/fhemtest.txt</code><br>
|
||||
<code>attr myFile filemode append</code><br>
|
||||
<code>set myFile add Textzeile 1</code><br>
|
||||
<code>set myFile add Textzeile 2</code><br>
|
||||
<code>set myMsg write myFile</code><br>
|
||||
<code>set myFile clear</code><br>
|
||||
</ul><br>
|
||||
|
||||
<ul><b>write</b><br> to write the message buffer to the associated file.</ul><br>
|
||||
</ul><br>
|
||||
Examples:
|
||||
<ul>
|
||||
<code>set myFile add Dies ist Textzeile 1</code><br>
|
||||
<code>set myFile add Dies ist Textzeile 2</code><br>
|
||||
<code>set myFile clear</code><br>
|
||||
<br>
|
||||
Full working example to write two lines of data to a file:<br>
|
||||
<code>define myFile MSGFile /tmp/fhemtest.txt</code><br>
|
||||
<code>attr myFile filemode append</code><br>
|
||||
<code>set myFile add Textzeile 1</code><br>
|
||||
<code>set myFile add Textzeile 2</code><br>
|
||||
<code>set myFile write</code><br>
|
||||
<code>set myFile clear</code><br>
|
||||
</ul><br>
|
||||
|
||||
<a name="MSGFileVattr"></a>
|
||||
<b>Attributes</b>
|
||||
|
@ -2,26 +2,30 @@
|
||||
# $Id$
|
||||
########################################################
|
||||
#
|
||||
# Created 2012 by rbente
|
||||
#
|
||||
########################################################
|
||||
#
|
||||
# History:
|
||||
#
|
||||
# 2015-05-06: tidy up code for restructuring
|
||||
# 2015-05-05: remove dependency on Switch
|
||||
#
|
||||
# 2015-05-09: Assimilate mail related code from 75_MSG
|
||||
# 2015-05-06: Tidy up code for restructuring
|
||||
# 2015-05-05: Remove dependency on Switch
|
||||
# 2012 : Created by rbente
|
||||
#
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use MIME::Lite;
|
||||
use Net::SMTP; # libnet-3.06 has SSL included, so we need to check the version
|
||||
|
||||
my %sets = (
|
||||
"add" => "MSGMail",
|
||||
"clear" => "MSGMail",
|
||||
"list" => "MSGMail"
|
||||
"list" => "MSGMail",
|
||||
"send" => "MSGMail"
|
||||
);
|
||||
|
||||
my $MSGMail_SSL = 0;
|
||||
my $MSGMail_SMTP = 0;
|
||||
|
||||
##############################################
|
||||
# Initialize Function
|
||||
# Attributes are:
|
||||
@ -43,79 +47,33 @@ sub MSGMail_Initialize($)
|
||||
$hash->{DefFn} = "MSGMail_Define";
|
||||
$hash->{UndefFn} = "MSGMail_Undef";
|
||||
$hash->{AttrList} = "loglevel:0,1,2,3,4,5,6 authfile smtphost smtpport subject from to cc CR:0,1";
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Set Function
|
||||
# all the data are stored in the global array @data
|
||||
# as counter we use a READING named msgcount
|
||||
##############################################
|
||||
sub MSGMail_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets)
|
||||
if (!defined($sets{ $a[1] }));
|
||||
my $name = shift @a;
|
||||
my $name = "MSGMail";
|
||||
|
||||
return "no set value specified" if (int(@a) < 1);
|
||||
|
||||
# return "Unknown argument ?" if($a[0] eq "?");
|
||||
my $v = join(" ", @a);
|
||||
# we like to add another line of data
|
||||
if ($a[0] eq "add")
|
||||
# check version of libnet - if < 3.00, try to load Net::SMTP::SSL
|
||||
$MSGMail_SMTP = $Net::SMTP::VERSION;
|
||||
if ($Net::SMTP::VERSION >= 3)
|
||||
{
|
||||
# split the line in command and data
|
||||
my $mx = shift @a;
|
||||
my $my = join(" ", @a);
|
||||
# check if we like to have and CR at the end of the line
|
||||
if (AttrVal($name, "CR", "0") eq "1")
|
||||
{
|
||||
$my = $my . "\n";
|
||||
}
|
||||
# get the highest number of lines, stored the line in @data and increase
|
||||
# the counter, at the end set the status
|
||||
my $count = $hash->{READINGS}{msgcount}{VAL};
|
||||
$data{$name}{$count} = $my;
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = $count + 1;
|
||||
$hash->{STATE} = "addmsg";
|
||||
|
||||
$MSGMail_SSL = 1;
|
||||
}
|
||||
# we like to clear our buffer, first clear all lines of @data
|
||||
# and then set the counter to 0 and the status to clear
|
||||
|
||||
elsif ($a[0] eq "clear")
|
||||
else
|
||||
{
|
||||
my $i;
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
eval "use Net::SMTP::SSL";
|
||||
if ($@)
|
||||
{
|
||||
$data{$name}{$i} = "";
|
||||
Log 0, $@ if ($@);
|
||||
$MSGMail_SSL = 0;
|
||||
}
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = 0;
|
||||
$hash->{STATE} = "clear";
|
||||
|
||||
}
|
||||
|
||||
# we like to see the buffer
|
||||
|
||||
elsif ($a[0] eq "list")
|
||||
{
|
||||
my $i;
|
||||
my $mess = "---- Lines of data for $name ----\n";
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
else
|
||||
{
|
||||
$mess .= $data{$name}{$i};
|
||||
$MSGMail_SSL = 1;
|
||||
}
|
||||
return "$mess---- End of data for $name ----";
|
||||
}
|
||||
Log GetLogLevel($name, 2), "messenger set $name $v";
|
||||
|
||||
# set stats
|
||||
# $hash->{CHANGED}[0] = $v;
|
||||
$hash->{READINGS}{state}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{state}{VAL} = $v;
|
||||
return undef;
|
||||
Log 2,
|
||||
"$name: SSL is "
|
||||
. ( ($MSGMail_SSL)
|
||||
? ("available, provided by Net::SMTP" . (($MSGMail_SMTP < 3.00) ? "::SSL" : ""))
|
||||
: "not available");
|
||||
}
|
||||
|
||||
##############################################
|
||||
@ -130,6 +88,7 @@ sub MSGMail_Define($$)
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
return $errmsg if (@a != 6);
|
||||
|
||||
# set all the Attributes
|
||||
$attr{$name}{from} = $a[2];
|
||||
$attr{$name}{to} = $a[3];
|
||||
@ -153,6 +112,7 @@ sub MSGMail_Undef($$)
|
||||
{
|
||||
my ($hash, $name) = @_;
|
||||
my $i;
|
||||
|
||||
# flush the data
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
@ -163,6 +123,183 @@ sub MSGMail_Undef($$)
|
||||
return undef;
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Set Function
|
||||
# all the data are stored in the global array @data
|
||||
# as counter we use a READING named msgcount
|
||||
##############################################
|
||||
sub MSGMail_Set($@)
|
||||
{
|
||||
my ($hash, @a) = @_;
|
||||
return "Unknown argument $a[1], choose one of -> " . join(" ", sort keys %sets)
|
||||
if (!defined($sets{ $a[1] }));
|
||||
my $name = shift @a;
|
||||
|
||||
return "no set value specified" if (int(@a) < 1);
|
||||
|
||||
# return "Unknown argument ?" if($a[0] eq "?");
|
||||
my $v = join(" ", @a);
|
||||
|
||||
# we like to add another line of data
|
||||
if ($a[0] eq "add")
|
||||
{
|
||||
# split the line in command and data
|
||||
my $mx = shift @a;
|
||||
my $my = join(" ", @a);
|
||||
|
||||
# check if we like to have and CR at the end of the line
|
||||
if (AttrVal($name, "CR", "0") eq "1")
|
||||
{
|
||||
$my = $my . "\n";
|
||||
}
|
||||
|
||||
# get the highest number of lines, stored the line in @data and increase
|
||||
# the counter, at the end set the status
|
||||
my $count = $hash->{READINGS}{msgcount}{VAL};
|
||||
$data{$name}{$count} = $my;
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = $count + 1;
|
||||
$hash->{STATE} = "addmsg";
|
||||
}
|
||||
|
||||
# we like to clear our buffer, first clear all lines of @data
|
||||
# and then set the counter to 0 and the status to clear
|
||||
|
||||
elsif ($a[0] eq "clear")
|
||||
{
|
||||
my $i;
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$data{$name}{$i} = "";
|
||||
}
|
||||
$hash->{READINGS}{msgcount}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{msgcount}{VAL} = 0;
|
||||
$hash->{STATE} = "clear";
|
||||
}
|
||||
|
||||
# we like to see the buffer
|
||||
|
||||
elsif ($a[0] eq "list")
|
||||
{
|
||||
my $i;
|
||||
my $mess = "---- Lines of data for $name ----\n";
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$mess .= $data{$name}{$i};
|
||||
}
|
||||
return "$mess---- End of data for $name ----";
|
||||
}
|
||||
|
||||
elsif ($a[0] eq "send")
|
||||
{
|
||||
# check all required data
|
||||
my $from = AttrVal($name, "from", "");
|
||||
my $to = AttrVal($name, "to", "");
|
||||
my $subject = AttrVal($name, "subject", "");
|
||||
my $authfile = AttrVal($name, "authfile", "");
|
||||
my $smtphost = AttrVal($name, "smtphost", "");
|
||||
my $smtpport = AttrVal($name, "smtpport", "465"); # 465 is the default port
|
||||
my $cc = AttrVal($name, "cc", ""); # Carbon Copy
|
||||
|
||||
return "No <from> address specified, use attr $name from <mail-address>"
|
||||
if (!$from);
|
||||
return "No <to> address specified, use attr $name to <mail-address>"
|
||||
if (!$to);
|
||||
return "No <subject> specified, use attr $name subject <text>"
|
||||
if (!$subject);
|
||||
return "No <authfile> specified, use attr $name authfile <filename>"
|
||||
if (!$authfile);
|
||||
return "No <smtphost> name specified, use attr $name sntphost <hostname>"
|
||||
if (!$smtphost);
|
||||
|
||||
open(FHEMAUTHFILE, "<" . $authfile)
|
||||
|| return "Can not open authfile $authfile: $!";
|
||||
my @auth = <FHEMAUTHFILE>;
|
||||
close(FHEMAUTHFILE);
|
||||
chomp(@auth);
|
||||
|
||||
# Log 1, "MSG User = <" . @auth[0] . "> Passwort = <" . @auth[1] . ">";
|
||||
|
||||
# compose message
|
||||
my $i;
|
||||
my $mess = "";
|
||||
for ($i = 0 ; $i < ReadingsVal($name, "msgcount", 0) ; $i++)
|
||||
{
|
||||
$mess .= $data{ $name }{$i};
|
||||
}
|
||||
|
||||
my $mailmsg = MIME::Lite->new(
|
||||
From => $from,
|
||||
To => $to,
|
||||
Subject => $subject,
|
||||
Type => 'text/plain; charset=UTF-8', #'multipart/mixed', # was 'text/plain'
|
||||
Data => $mess
|
||||
);
|
||||
|
||||
# login to the SMTP Host using SSL and send the message
|
||||
my $smtp;
|
||||
my $smtperrmsg = "SMTP Error: ";
|
||||
|
||||
#$smtp = Net::SMTP::SSL->new($smtphost, Port => $smtpport)
|
||||
$smtp = MSGMail_conn($defs{ $name })
|
||||
or return $smtperrmsg . " Can't connect to host $smtphost";
|
||||
$smtp->auth($auth[0], $auth[1])
|
||||
or return $smtperrmsg . " Can't authenticate: " . $smtp->message();
|
||||
$smtp->mail($from) or return $smtperrmsg . $smtp->message();
|
||||
$smtp->to($to) or return $smtperrmsg . $smtp->message();
|
||||
if ($cc ne '')
|
||||
{
|
||||
Log 1, "CC = $cc";
|
||||
$smtp->cc($cc) or return $smtperrmsg . $smtp->message();
|
||||
}
|
||||
$smtp->data() or return $smtperrmsg . $smtp->message();
|
||||
$smtp->datasend($mailmsg->as_string)
|
||||
or return $smtperrmsg . $smtp->message();
|
||||
$smtp->dataend() or return $smtperrmsg . $smtp->message();
|
||||
$smtp->quit() or return $smtperrmsg . $smtp->message();
|
||||
|
||||
Log 1, "<MSG> send EMail: <$subject>";
|
||||
|
||||
} ###> END MSGMail
|
||||
|
||||
Log GetLogLevel($name, 2), "messenger set $name $v";
|
||||
|
||||
# set stats
|
||||
# $hash->{CHANGED}[0] = $v;
|
||||
$hash->{READINGS}{state}{TIME} = TimeNow();
|
||||
$hash->{READINGS}{state}{VAL} = $v;
|
||||
return undef;
|
||||
}
|
||||
|
||||
##############################################
|
||||
# Helper Function to connect to mail server
|
||||
# Returns a smtp connection (see Net:SMTP)
|
||||
##############################################
|
||||
sub MSGMail_conn($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
my ($name) = $hash->{NAME};
|
||||
|
||||
my $smtphost = AttrVal($name, "smtphost", "");
|
||||
my $smtpport = AttrVal($name, "smtpport", "465"); # 465 is the default port
|
||||
|
||||
if ($MSGMail_SSL)
|
||||
{
|
||||
if ($MSGMail_SMTP < 3.00)
|
||||
{
|
||||
Log3 $name, 3, "$name: try to connect with Net::SMTP::SSL";
|
||||
return Net::SMTP::SSL->new($smtphost, Port => $smtpport);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log3 $name, 3, "$name: try to connect with Net::SMTP";
|
||||
return Net::SMTP->new(Host => $smtphost, Port => $smtpport, SSL => 1);
|
||||
}
|
||||
}
|
||||
Log3 $name, 0, "$name: SSL not available. Connection will fail";
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
@ -171,13 +308,12 @@ sub MSGMail_Undef($$)
|
||||
<a name="MSGMail"></a>
|
||||
<h3>MSGMail</h3>
|
||||
<ul>
|
||||
The MSGMail device is a frontend device for mail message handling.
|
||||
With a MSGMaildevice data is fowarded to a mail provider and send to a recipent.
|
||||
Multiple MSGMail devices could be defined.
|
||||
MSGMail supports by the moment only mail provider, which uses SSL secured connection
|
||||
like Googlemail, GMX, Yahoo or 1und1 for example.
|
||||
To send an email, a MSG device is necessary.<br>
|
||||
<b>MAIL::Lite</b> and <b>Net::SMTP::SSL</b> from CPAN is needed to use MSGMail!!
|
||||
The MSGMail device is used to send mail messages to a recipient by connecting
|
||||
to a SMTP server. Currently MSGMail supports only servers, that allow SSL secured connections
|
||||
like Googlemail, GMX, Yahoo or 1und1.
|
||||
MSGMail requires the perl pacakge <b>MAIL::Lite</b>.
|
||||
For SSL support, Net::SMTP version 3.06 is required. On systems with an older version of Net::SMTP,
|
||||
MSGMail requires the package <b>Net::SMTP::SSL</b>.
|
||||
<br><br>
|
||||
|
||||
<a name="MSGMailDefine"></a>
|
||||
@ -196,7 +332,7 @@ sub MSGMail_Undef($$)
|
||||
|
||||
<a name="MSGMailSet"></a>
|
||||
<b>Set</b><br>
|
||||
<ul><code>set <name> add|clear|list [text]</code><br>
|
||||
<ul><code>set <name> add|clear|list|send [text]</code><br>
|
||||
Set is used to manipulate the message buffer of the device. The message
|
||||
buffer is an array of lines of data, stored serial based on the incoming
|
||||
time into the buffer. Lines of data inside the buffer could not be deleted
|
||||
@ -205,9 +341,10 @@ sub MSGMail_Undef($$)
|
||||
"add" will be interpreted as text message. To add a carriage return to the data,
|
||||
please use the CR attribute.
|
||||
</ul>
|
||||
<ul><b>clear</b><br> to flash the message buffer and set the line counter to 0.
|
||||
<ul><b>clear</b><br> to flush the message buffer and set the line counter to 0.
|
||||
All the lines of data are deleted and the buffer is flushed.</ul>
|
||||
<ul><b>list</b><br> to list the message buffer.<br></ul><br>
|
||||
<ul><b>send</b><br> to send the message buffer.<br></ul><br>
|
||||
<br>
|
||||
Examples:
|
||||
<ul>
|
||||
@ -215,14 +352,13 @@ sub MSGMail_Undef($$)
|
||||
<code>set myMail add Dies ist Textzeile 2</code><br>
|
||||
<code>set myMail clear</code><br><br>
|
||||
Full working example to send two lines of data to a recipent:<br>
|
||||
<code>define myMsg MSG</code><br>
|
||||
<code>define myMail MSGMail donald.duck@entenhausen.com dagobert.duck@duck-banking.com smtp.entenhausen.net /etc/fhem/msgmailauth</code><br>
|
||||
<code>attr myMail smtpport 9999</code><br>
|
||||
<code>attr myMail subject i need more money</code><br>
|
||||
<code>attr myMail CR 0</code><br>
|
||||
<code>set myMail add Please send me </code><br>
|
||||
<code>set myMail add 1.000.000 Taler</code><br>
|
||||
<code>set myMsg send myMail</code><br>
|
||||
<code>set myMail send</code><br>
|
||||
<code>set myMail clear</code><br>
|
||||
</ul><br>
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user