151 lines
3.7 KiB
Rust
151 lines
3.7 KiB
Rust
extern crate anyhow;
|
|
extern crate clokwerk;
|
|
extern crate lettre;
|
|
extern crate lettre_email;
|
|
extern crate log;
|
|
extern crate my_internet_ip;
|
|
extern crate native_tls;
|
|
extern crate serde;
|
|
extern crate simplelog;
|
|
extern crate toml;
|
|
|
|
use self::native_tls::{Protocol, TlsConnector};
|
|
use anyhow::{bail, Result};
|
|
use clokwerk::{Scheduler, TimeUnits};
|
|
use lettre::smtp::authentication::Credentials;
|
|
use lettre::{ClientSecurity, ClientTlsParameters, SmtpClient, Transport};
|
|
use lettre_email::EmailBuilder;
|
|
use log::{error, info};
|
|
use serde::Deserialize;
|
|
use simplelog::{ConfigBuilder, LevelFilter, WriteLogger};
|
|
use std::fs::{self, OpenOptions};
|
|
use std::net::IpAddr;
|
|
use std::path::Path;
|
|
use std::{thread, time::Duration};
|
|
|
|
fn main() -> Result<()> {
|
|
// Init log
|
|
let logfile = OpenOptions::new()
|
|
.append(true)
|
|
.create(true)
|
|
.open("log.txt")
|
|
.unwrap();
|
|
WriteLogger::init(
|
|
LevelFilter::Info,
|
|
ConfigBuilder::new()
|
|
.set_time_format_str("%d/%m/%Y %H:%M:%S")
|
|
.set_time_to_local(true)
|
|
.build(),
|
|
logfile,
|
|
)
|
|
.unwrap();
|
|
|
|
// Init scheduler
|
|
let mut scheduler = Scheduler::new();
|
|
info!("Init");
|
|
scheduler.every(1.day()).at("06:00").run(|| {
|
|
if let Err(e) = check() {
|
|
error!("Error {}", e);
|
|
}
|
|
});
|
|
|
|
// Initial check
|
|
if let Err(e) = check() {
|
|
error!("Error {}", e);
|
|
bail!("Cannot get initial IP");
|
|
}
|
|
|
|
// Run
|
|
loop {
|
|
scheduler.run_pending();
|
|
thread::sleep(Duration::from_secs(60));
|
|
}
|
|
}
|
|
|
|
fn check() -> Result<()> {
|
|
info!("Check");
|
|
match get() {
|
|
Ok((old_ip, new_ip)) => {
|
|
if old_ip != new_ip {
|
|
let msg = format!("IP changed from {} to {}", old_ip, new_ip);
|
|
info!("{}", msg);
|
|
send_mail("New IP".to_owned(), msg)?;
|
|
}
|
|
}
|
|
Err(err) => {
|
|
let msg = format!("Cannot get IP ({})", err);
|
|
error!("{}", msg);
|
|
send_mail("Error on getting IP".to_owned(), msg)?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn get() -> Result<(IpAddr, IpAddr)> {
|
|
// Get new IP
|
|
let new_ip = match my_internet_ip::get() {
|
|
Ok(ip) => ip,
|
|
Err(e) => bail!("Could not get IP: {:?}", e),
|
|
};
|
|
info!("Current IP is {}", new_ip);
|
|
|
|
// Get old IP
|
|
let path = Path::new("./old_ip.txt");
|
|
let old_ip = if path.exists() {
|
|
fs::read_to_string(path)?.parse()?
|
|
} else {
|
|
new_ip.clone()
|
|
};
|
|
info!("Old IP is {}", old_ip);
|
|
|
|
// Write new IP
|
|
fs::write(path, format!("{}", new_ip))?;
|
|
|
|
Ok((old_ip, new_ip))
|
|
}
|
|
|
|
fn send_mail(subject: String, body: String) -> Result<()> {
|
|
info!("Send mail {}", subject);
|
|
|
|
let config: Config = toml::from_str(&fs::read_to_string("config.toml")?)?;
|
|
|
|
let email = EmailBuilder::new()
|
|
.to(config.mail.from)
|
|
.from(config.mail.to)
|
|
.subject(subject)
|
|
.text(body)
|
|
.build()?;
|
|
|
|
// Create transport
|
|
let creds = Credentials::new(config.mail.username, config.mail.password);
|
|
let mut tls_builder = TlsConnector::builder();
|
|
tls_builder.min_protocol_version(Some(Protocol::Sslv3));
|
|
let tls_parameters =
|
|
ClientTlsParameters::new(config.mail.server.clone(), tls_builder.build().unwrap());
|
|
let mut mailer = SmtpClient::new(
|
|
(config.mail.server, config.mail.port),
|
|
ClientSecurity::Required(tls_parameters),
|
|
)?
|
|
.credentials(creds)
|
|
.transport();
|
|
|
|
mailer.send(email.into())?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct Config {
|
|
mail: MailConfig,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
struct MailConfig {
|
|
server: String,
|
|
port: u16,
|
|
username: String,
|
|
password: String,
|
|
from: (String, String),
|
|
to: String,
|
|
}
|