Control you smarthome with mails

Smarthome-Steuerung mit Mail

A smarthome offers a lot of possibilities. Today, almost everything can be interconnected in this context, providing more convenience, quality of living, cost savings and security. If you want to access via the Internet, there are still some risks.

Starting from lighting to heating or camera surveillance to your washing machine – almost everything can now be connected to a smarthome. This is convenient and once you get used to it, you usually want to be able to have some functions not only in the local LAN.

But then it is necessary to make your system accessible via the Internet. With this step you are much more vulnerable from outside. You need to keep your system always up to date. A residual risk remains, even if you work with a Raspberry Pi under Debian with a very secure system.

Because of this I am currently not ready to open my system for the Internet. Nevertheless, I would like to use the advantages.

But the smarthome computer is usually still connected to the Internet via your network and a router. Why not use this existing connection? This may not be the most beautiful solution possible, but a safe one.

A mail control

I would like to show you an example of this solution for such a possible intermediate stage: an e-mail control.

Control smarthome with mails
Control-system with mails

On your computer with the smarthome software, another software checks regularly your mailbox. When a message meets certain criteria, the software starts actions.

In my case the smarthome computer is a Raspberry Pi. A cron job regularly – every 5 minutes – checks my special smarthome mailbox for new messages. Which minimum interval is possible depends on the mail provider. Some providers do not allow small intervals.

To ensure a high level of security here, several conditions must be met before an action is triggered. What are these steps? You’ll find mine in the following figure.

Steps to perform a valid action
Steps to perform a valid action

An example of an e-mail for a query might look like this:

From: name@provider.de
To: smarthome@provider.de
Subject: SH
Message:
**STATE
**LIGHT_G_OFF

Only if the subject is SH and the sender adress name@provider.de has permission and valid commands are included ( **STATE, **LIGHT .. ) , the actions are performed by the software.

Examples of commands:

** STATE       Could send back an email with interesting states in the message body, e. g.  doors are open, which lights are on, etc.

** REBOOT   Reboots the Raspberry Pi. This is not often necessary, but sometimes useful.

But you can also set actuators as a light. By the time offset of mail retrieval, which is obviously not useful for a direct control. But a forgotten light could be turned off. In my case it works with this command:

** LIGHT_G_OFF   Turns off the lights in the garage.

** …

 

Realization with Lazarus and Free Pascal

You fetch messages from the mailbox via the IMAP protocol. To do this there are several settingsnecessary – depending on your mail provider. In the source code, the values ​​are stored as constants.

IMAP_HOST = 'imap.1und1.com';
IMAP_PORT = '993'; //or 143
MAIL_USER = 'smarthome@ihreadresse.de';
MAIL_PASSWORD = 'secret';

Lazarus does not provide functions working with mails by default. But there is a very good library Synapse from Ararat. You can find the download link at the end of this article. Unpack the archive to any folder and add the folder to the project. Alternatively, you click ADD FILES FROM THE FILE SYSTEM in the project inspector and select imapsend.pas in Synapse folder.

Lib einfügen
Add folder of the synapse library in the project settings

Programming the library is very simple. In the sample application all steps to check the mailbox for new mails is stored in the procedure CheckMailbox.

procedure CheckMailbox;
var
  s, user : string;
  j, cnt ,spcnt : integer;
  mail : TStringList;
  Imap : TIMAPSend;
  MimeMess : TMimeMess;
  MimePart : TMimePart;
begin
  mail:=TStringList.Create;
  imap:=TIMAPSend.create;
  MimeMess:=TMimeMess.Create;

  //Settings for IMAP
  Imap.TargetHost:=IMAP_HOST;
  Imap.TargetPort:=IMAP_PORT;
  Imap.UserName:=MAIL_USER;
  Imap.Password:=MAIL_PASSWORD;
  Imap.AutoTLS:=false;
  Imap.FullSSL:=false;

  if Imap.Login then
    begin
      //Are the new messages?
      cnt:=Imap.StatusFolder('INBOX','UNSEEN');
      if cnt>0 then
        begin
          Output('There are new mails ('+IntToStr(cnt)+').');
          Imap.SelectFolder('INBOX'); //select Inbox
          //check every new mail
          for j:=Imap.SelectedCount-Imap.SelectedRecent+1 to Imap.SelectedCount do
            begin
              Imap.FetchMess(j,MimeMess.Lines); //fetch mail
              MimeMess.DecodeMessage;
              Output('');
              Output('---');
              output('Checking: '+MimeMess.Header.Subject+' from '+MimeMess.Header.From);
              //check valid user and valid subject?
              if (ValidUsers.IsValid(MimeMess.Header.From)=true)
                and (Uppercase(MimeMess.Header.Subject)=ACTION_SUBJECT) then
                begin
                  mail.Clear;
                  user:=MimeMess.Header.From;
                  spcnt:=MimeMess.MessagePart.GetSubPartCount();
                  Output('>>> Valid mail');
                  if spcnt>0 then
                    for cnt:=0 to {spcnt-1} 0 do
                      begin
                        MimePart:=MimeMess.MessagePart.GetSubPart(cnt);
                        MimePart.DecodePart;
                        mail.Add(MimePart.Primary);
                        mail.Add(MimePart.Secondary);
                        setlength(s,MimePart.DecodedLines.Size);
                        MimePart.DecodedLines.Read(s[1],length(s));
                        mail.Add(s);
                      end
                  else mail.AddStrings(MimeMess.MessagePart.Lines);
                  //output(mail.Text);
                  //Gibt es Aktionen??
                  //Which actions should be executed?
                  if Pos('**STATE',mail.Text)>0 then ActionStateMail(user);
                  if Pos('**LIGHT_G_ON',mail.Text)>0 then ActionRunScript('/home/pi/scripts/light_g_on');
                  if Pos('**LIGHT_G_OFF',mail.Text)>0 then ActionRunScript('/home/pi/scripts/light_g_off');
                  if Pos('**REBOOT',mail.Text)>0 then ActionRunScript('/home/pi/scripts/reboot_pi');
                  if Pos('**HELP',mail.Text)>0 then ActionHelp(user);
                end;
            end;
        end else Output('There are no new mails');
    end else Output('Login failed!');
  MimeMess.Free;
  Imap.free;
  mail.Free;
end;

 

Perform actions

In the last part of the above procedure your possible actions are defined. Only your imagination is the limit! In the source code I have installed two basic functions as an example.

a) Mail

To send an email, another procedure is SendToEx of Synape used.

function Sendmail(const MailTo, Subject: string; const Mail Data: TStrings): boolean;
begin
  Result: = SendToEx(MAIL_USER, MailTo, Subject, smtp_host, Maildata,
  MAIL_USER, MAIL_PASSWORD);
end;

The constants MAIL_USER, MAIL_PASSWORD have already been defined. The SMTP host is still required to send a mail.

Here is an example for the provider 1und1:

SMTP_Host = 'smtp.1und1.com';

A useful function could be a status mail about interesting states in your smart home. In my case, the status values are available as text files on the Raspberry Pi. These files are read and converted into a text. All text is stored in a TStringList and copied to the mail body text.

b) Run scripts / start programs

Lazarus and Free Pascal offer a number of ways to start other programs or scripts. If you want to work across platforms, the object TProcess is quite well.

ActionRunScript procedure (script: string);
var
  Process: TProcess;
begin
  Process: = TProcess.Create (nil);
  Process.CommandLine: = script;
  Process.Options: = Process.Options + [poWaitOnExit];
  Process.Execute;
  Process.Free;
  Output('command ' + script + ' executed.');
end;

 

Example project and outlook

In the download area you can find an example project for a console application. It is based on the above-described source code. You can use it with Windows or Linux.

But for a meaningful use, you must regularly run it with Cron.

If there is no new mail in your mailbox, the application looks like this:

Test application mailchecker
Test application mailchecker: no new mails!

An example when there are new messages with the appropriate keyword looks like that:

Test application mailchecker
Test application mailchecker: new mails!

Update the constants in mailcheck.pas to your mailbox settings and develop the project for your application. Maybe with a little HTML, a reply e-mail could show a smarthome state, which is a little bit more stylish.

You might also find better ways to use this control mode.

Good look for your experiments!

Download

symbol_download


Example project for Lazarus

For the compilation you need the Library Synapse. You can download it under http://synapse.ararat.cz/doku.php/download. Is Lazarus not already installed on your computer, take a look at this article Lazarus installieren (sorry only German).

 

Links

Article by Michaël Van Canneyt to send mail with Lazarus
https://www.freepascal.org/~michael/articles/lazmail/lazmail-en.pdf

Wikipedia articles on IMAP
https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol

Wiki of Lazarus on TProcess
http://wiki.freepascal.org/Executing_External_Programs

Wiki about Synapse
http://wiki.freepascal.org/Synapse

Wikipedia entry on Cron
https://de.wikipedia.org/wiki/Cron


Klicken Sie hier, um diesen Artikel in Deutsch zu lesen.