This shows you the differences between two versions of the page.
Last revision | |||
— | sdk:scripts:email-to-sms [2015/05/05 15:04] – external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== SDK Script email-to-sms.are ====== | ||
+ | <code c email-to-sms.are> | ||
+ | /* DESC: This script implements a lightweight SMTP server which is able to receive mail and forward them as SMS to a phone number. | ||
+ | * Copyright (C) 2012 NetModule AG, Switzerland | ||
+ | */ | ||
+ | |||
+ | MAX_CONECTIONS | ||
+ | TIMEOUT | ||
+ | MAX_ERRORS | ||
+ | MAX_MESSAGES | ||
+ | MAX_HEADER_LEN | ||
+ | MAX_BODY_LEN | ||
+ | DOMAIN | ||
+ | AUTHENTICATE | ||
+ | |||
+ | ALLOWED_SENDERS = mkarray(" | ||
+ | " | ||
+ | | ||
+ | ALLOWED_NUMBERS = mkarray(" | ||
+ | " | ||
+ | |||
+ | string extract_addr (string str) | ||
+ | { | ||
+ | addr = trim(str); | ||
+ | |||
+ | /* check for @ */ | ||
+ | pos = strchr(addr, | ||
+ | if (is_void(pos) || pos == 0) { | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | pos = strchr(addr, | ||
+ | if (!is_void(pos)) { | ||
+ | addr = substr(addr, | ||
+ | pos = strchr(addr, | ||
+ | if (is_void(pos) || pos < 1) { | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | addr = left(addr, pos); | ||
+ | } | ||
+ | |||
+ | return addr; | ||
+ | } | ||
+ | |||
+ | string validate_sender (string from) | ||
+ | { | ||
+ | /* extract mail addr */ | ||
+ | sender = extract_addr(from); | ||
+ | if (strlen(sender) == 0) return ""; | ||
+ | |||
+ | /* check if sender is allowed */ | ||
+ | for (i = 0; i < length(ALLOWED_SENDERS); | ||
+ | s = ALLOWED_SENDERS[i]; | ||
+ | if (left(sender, | ||
+ | nb_syslog(" | ||
+ | return sender; | ||
+ | } | ||
+ | } | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | string validate_number (string rcpt) | ||
+ | { | ||
+ | /* extract mail addr */ | ||
+ | addr = extract_addr(rcpt); | ||
+ | if (strlen(addr) == 0) return ""; | ||
+ | |||
+ | pos = strchr(addr, | ||
+ | if (is_void(pos) || pos == 0) { | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | number = left(addr, pos); | ||
+ | domain = substr(addr, | ||
+ | |||
+ | if (domain != DOMAIN) { | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | if (left(number, | ||
+ | nb_syslog(" | ||
+ | return ""; | ||
+ | } | ||
+ | |||
+ | for (i = 0; i < length(ALLOWED_NUMBERS); | ||
+ | n = ALLOWED_NUMBERS[i]; | ||
+ | if (left(number, | ||
+ | nb_syslog(" | ||
+ | return number; | ||
+ | } | ||
+ | } | ||
+ | nb_syslog(" | ||
+ | return number; | ||
+ | } | ||
+ | |||
+ | string add_to_header (string header, string msg) | ||
+ | { | ||
+ | if ((strlen(header) + strlen(msg) + 1) > MAX_HEADER_LEN) { | ||
+ | nb_syslog(" | ||
+ | return header; | ||
+ | } | ||
+ | return strcat(header, | ||
+ | } | ||
+ | |||
+ | string add_to_body (string body, string msg) | ||
+ | { | ||
+ | len = strlen(body) + strlen(msg) + 1; | ||
+ | |||
+ | if (len > MAX_BODY_LEN) { | ||
+ | nb_syslog(" | ||
+ | return body; | ||
+ | } | ||
+ | return strcat(body, | ||
+ | } | ||
+ | |||
+ | void usage() | ||
+ | { | ||
+ | nb_syslog(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* main */ | ||
+ | |||
+ | if (argc < 2) { | ||
+ | usage(); | ||
+ | } | ||
+ | |||
+ | PORT = (int) argv[1]; | ||
+ | HOSTNAME = nb_config_get(" | ||
+ | if (strlen(hostname) == 0) { | ||
+ | HOSTNAME = " | ||
+ | } | ||
+ | if (AUTHENTICATE) { | ||
+ | PASSWORD = nb_config_get(" | ||
+ | if (strlen(PASSWORD) == 0) { | ||
+ | PASSWORD = " | ||
+ | } | ||
+ | } | ||
+ | |||
+ | st = nb_config_get(" | ||
+ | if (st != " | ||
+ | nb_syslog(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | if (PORT < 1024 || PORT >= 65536) { | ||
+ | nb_syslog(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* raise socket */ | ||
+ | |||
+ | sock = socket(AF_INET, | ||
+ | if (sock < 0) { | ||
+ | nb_syslog(" | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | ret = bind(sock, PORT, "" | ||
+ | if (ret == -1) { | ||
+ | nb_syslog(" | ||
+ | close(sock); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | ret = listen(sock, | ||
+ | if (ret == -1) { | ||
+ | nb_syslog(" | ||
+ | close(sock); | ||
+ | exit(1); | ||
+ | } | ||
+ | |||
+ | /* listen for clients */ | ||
+ | nb_syslog(" | ||
+ | state = " | ||
+ | |||
+ | while (1) { | ||
+ | client = accept(sock); | ||
+ | if (client < 0) { | ||
+ | printf(" | ||
+ | sleep(1); | ||
+ | continue; | ||
+ | } | ||
+ | | ||
+ | nb_syslog(" | ||
+ | user = pass = number = rcpt = sender = header = body = subject = ""; | ||
+ | errors = messages = 0; | ||
+ | |||
+ | state = " | ||
+ | send(client, | ||
+ | |||
+ | while (1) { | ||
+ | /* wait for socket data */ | ||
+ | rv = select(client, | ||
+ | if (rv == -1) { | ||
+ | nb_syslog(" | ||
+ | break; | ||
+ | } else if (rv == 0) { | ||
+ | nb_syslog(" | ||
+ | break; | ||
+ | } else { | ||
+ | /* data available */ | ||
+ | msg = recv(client); | ||
+ | if (strlen(msg) == 0) { | ||
+ | nb_syslog(" | ||
+ | break; | ||
+ | } | ||
+ | messages++; | ||
+ | |||
+ | if (errors > MAX_ERRORS || messages > MAX_MESSAGES) { | ||
+ | nb_syslog(" | ||
+ | send(client," | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | pos1 = strchr(msg, " | ||
+ | pos2 = strchr(msg, " | ||
+ | if (pos1 >= 0 && pos1 < pos2) { | ||
+ | pos = pos1; | ||
+ | } else { | ||
+ | pos = pos2; | ||
+ | } | ||
+ | if (!is_void(pos)) { | ||
+ | line = substr(msg, 0, pos); | ||
+ | cmd = tolower(line); | ||
+ | } else { | ||
+ | /* not a valid command */ | ||
+ | line = cmd = ""; | ||
+ | } | ||
+ | |||
+ | /* | ||
+ | dump(msg); | ||
+ | nb_syslog(" | ||
+ | */ | ||
+ | |||
+ | if (left(cmd, 4) == " | ||
+ | send(client," | ||
+ | state = " | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | if (state == " | ||
+ | /* expect hello */ | ||
+ | if (left(cmd, 4) == " | ||
+ | state = " | ||
+ | send(client, | ||
+ | } else if (left(cmd, 4) == " | ||
+ | if (AUTHENTICATE) { | ||
+ | state = " | ||
+ | send(client, | ||
+ | " | ||
+ | | ||
+ | } else { | ||
+ | state = " | ||
+ | send(client, | ||
+ | } | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else if (state == " | ||
+ | if (AUTHENTICATE && state != " | ||
+ | if (left(cmd, 10) == "auth login" | ||
+ | /* prompt for username */ | ||
+ | send(client, | ||
+ | state = " | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else { | ||
+ | /* expect mail from */ | ||
+ | if (left(cmd, 10) == "mail from:" | ||
+ | /* rewind mail settings */ | ||
+ | user = pass = number = rcpt = sender = header = body = subject = ""; | ||
+ | |||
+ | sender = validate_sender(substr(cmd, | ||
+ | if (strlen(sender) > 0) { | ||
+ | state = " | ||
+ | send(client, | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } | ||
+ | } else if (state == " | ||
+ | /* read username */ | ||
+ | user = base64_decode(trim(line)); | ||
+ | if (user != " | ||
+ | nb_syslog(" | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } else { | ||
+ | send(client, | ||
+ | state = " | ||
+ | } | ||
+ | } else if (state == " | ||
+ | /* read username */ | ||
+ | pass = base64_decode(trim(line)); | ||
+ | if (pass != PASSWORD) { | ||
+ | nb_syslog(" | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } else { | ||
+ | nb_syslog(" | ||
+ | send(client, | ||
+ | state = " | ||
+ | } | ||
+ | } else if (state == " | ||
+ | /* expect rcpt to */ | ||
+ | if (left(cmd, 8) == "rcpt to:") { | ||
+ | number = validate_number(substr(cmd, | ||
+ | if (strlen(number) > 0) { | ||
+ | state = " | ||
+ | send(client, | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else if (state == " | ||
+ | /* expect DATA */ | ||
+ | if (left(cmd, 4) == " | ||
+ | state = " | ||
+ | send(client, | ||
+ | } else { | ||
+ | send(client, | ||
+ | errors++; | ||
+ | } | ||
+ | } else if (state == " | ||
+ | gotEOF = 0; | ||
+ | pos = strstr(msg, " | ||
+ | if (!is_void(pos)) { | ||
+ | gotEOF = 1; | ||
+ | msg = left(msg, pos); | ||
+ | } | ||
+ | |||
+ | if (state != " | ||
+ | pos = strstr(msg, " | ||
+ | if (is_void(pos)) pos = strstr(msg, " | ||
+ | |||
+ | if (is_void(pos)) { | ||
+ | header = add_to_header(header, | ||
+ | } else { | ||
+ | state = " | ||
+ | header = add_to_header(header, | ||
+ | body = add_to_body(body, | ||
+ | } | ||
+ | } else { | ||
+ | body = add_to_body(body, | ||
+ | } | ||
+ | |||
+ | if (gotEOF) { | ||
+ | if (state != " | ||
+ | nb_syslog(" | ||
+ | send(client," | ||
+ | errors++; | ||
+ | } else { | ||
+ | body = trim(body); | ||
+ | if (strlen(body) > 0 && strlen(number) > 0) { | ||
+ | /* dump(body); */ | ||
+ | |||
+ | nb_syslog(" | ||
+ | id = nb_sms_send(number, | ||
+ | if (id) { | ||
+ | nb_syslog(" | ||
+ | send(client," | ||
+ | errors = 0; | ||
+ | } else { | ||
+ | nb_syslog(" | ||
+ | send(client," | ||
+ | errors++; | ||
+ | } | ||
+ | } else { | ||
+ | nb_syslog(" | ||
+ | send(client," | ||
+ | errors++; | ||
+ | } | ||
+ | } | ||
+ | state = " | ||
+ | } | ||
+ | } else { | ||
+ | nb_syslog(" | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | nb_syslog(" | ||
+ | close(client); | ||
+ | } | ||
+ | |||
+ | nb_syslog(" | ||
+ | close(sock); | ||
+ | |||
+ | exit(0); | ||
+ | |||
+ | </ | ||