Free vient de mettre à disposition de ses abonnés Free-mobile un moyen simple de générer via une API accessible en ligne des SMS à soi-même. L'utilisation est globalement très simple et tient presque toutes ses promesses (actuellement il ne semble pas possible de faire du POST
, seul le GET
fonctionne).
Il suffit aux intéressés de se rendre sur leur interface de gestion de compte Free-mobile, dans la section "Mes options", et d'y activer (vers le bas de la page) l'option ad-hoc. Une fois l'option activée, Free vous gratifie d'un mot de passe dédié à cet usage, et vous renseigne un peu sur le fonctionnement du service :
Une fois l'option activée, l'utilisation se résume à une requête HTTP
de cette forme :
curl 'https://smsapi.free-mobile.fr/sendmsg?user=***&pass=***&msg=coucou'
Vous recevez alors sur votre téléphone Free-mobile le SMS contenant le message "coucou".
La création d'un message multiligne est un peu plus délicate. La plupart des plateforme Unix/Linux envoie en guise de séparateur de ligne un \n
qui se traduit par %0a
une fois "url-encodé". Malheureusement, l'API n'accepte pas ce %0a
et le message sera tronqué à la première occurrence.
Par contre, le séparateur de ligne \r
, encodé en %0d
est bien accepté par l'API Free-mobile. Il faut donc, avant d'envoyer un message sur plusieurs lignes, traduire les \n
en \r
.
J'ai conçu un script shell pour mes besoins personnels. Il prend ses données en entrée standard, par exemple via un pipe :
echo "mon message" | sms.sh
Ce qui est plus souple pour moi dans bien des situations, que de devoir invoquer le script et de lui servir le message comme argument, par exemple :
autresms.sh mon message
Voici donc le code de mon script qui prend les messages via stdin
, et qui converti les \n
en \r
. Notez que le SMS à l'arrivée ne contient pas de saut de ligne, donc prévoyez des espaces en fin de ligne si vous ne voulez pas que la fin de ligne soit collée au début de la ligne suivante.
#!/usr/local/bin/bash # # push notification via smsapi.free-mobile.fr # LOGGEROPT="-p security.notice -t SMS" REPLOGG=1 REPMAIL=1 MAILTO=root USR="****" PSW="****" URL="https://smsapi.free-mobile.fr/sendmsg" CURL=/usr/local/bin/curl report() { [ ${REPLOGG} -eq 1 ] && echo $@ | logger ${LOGGEROPT} [ ${REPMAIL} -eq 1 ] && echo $@ | mail -s "SMS $@" ${MAILTO} } eval $(${CURL} --insecure -G --write-out "c=%{http_code} u=%{url_effective}" \ -o /dev/null -L -d user=${USR} -d pass=${PSW} --data-urlencode msg="$(cat|tr '\n' '\r')" ${URL} 2>/dev/null | tr '&' ';') echo ${c} ${u}\&pass=***\&msg=${msg} | logger ${LOGGEROPT} case ${c} in "200") exit 0 ;; "400") report "parameter missing" ; exit 400 ;; "402") report "too many SMS..." ; exit 402 ;; "403") report "service unavailable for user, or wrong credentials" ; exit 403 ;; "500") report "server error, try later" ; exit 500 ;; *) report "unexpected result" ; exit 600 ;; esac
Utilisation :
echo "mon message sur plusieurs lignes" | sms.sh
Il reste à faire :
- ajouter l'enregistrement dans les log système de chaque utilisation du script sms.sh
- ajouter la gestion des codes de retour HTTP
autres que 200.
Attention
Pour bénéficier d'une gestion d'erreur et d'une trace dans les log de la machine j'ai utilisé une grosse ruse très sale avec eval
. Cela permet de créer des variables à la volée à partir de données fournie par l'utilisateur. C'est éminemment risqué car tout ce est qui généré par c=%{http_code} u=%{url_effective}
sera évalué sans distinction (avec potentiellement des exécutions de code).
Pour un système de monitoring c'est un risque négligeable : les messages sont connus et fixés par le logiciel qui les génère, sans interaction avec l'utilisateur. Pour une utilisation dans tout autre mécanisme la prudence est requise.
Les SMS arrivent en une seule ligne ?
Sur mon script (https://github.com/C-Duv/freemobile-smsapi-client/blob/master/send-notification.sh) j'utilise "%0D" et je reçois plusieurs lignes (eg. `free | send-notification.sh`).
Je me demande si ça ne peut pas aussi dépendre du logiciel de rendu du SMS sur le mobile (certains seraient plus "sympas" que d'autres).
Oui, chez moi ils arrivent en une seule ligne (Android 4.3, application SMS par défaut).
J'utilise bien %0D comme séparateur (de toute manière %0A ne passe pas).
Quoi qu'il en soit ce n'est pas un drame :)
J'ai avancé sur la partie "log système" des appels au script avec un gros hack quick & dirty, et dans la foulée je vais ajouter la gestion des erreurs dans le courant de la semaine.
Si ça intéresse, j'ai commis un bout de code (très sale) en PHP...
https://gitlab.com/microniko/mysms
Des fois que ça serve à quelqu'un...
Les bleus n'étaient pas à l'honneur ici.
On a perdu alors tant pis.
Les bleus n'ont pas été si mauvais.
On doit rêver.
2016 en France ? 2018 en Russie ?
Un roman de SF et de football, Brasyl de Ian McDonald
Testé aujourd'hui, \r ne passe pas, mais \n (%0a) fonctionne bien pour un retour à la ligne dans les messages.
hi,
did you try the POST method?
doesn't work for me...
(GET method is fine though)
thanks
en fait POST marche avec:
'content-type' => "application/json"
(duvergier a vire le commentaire que
j'ai laisse sur son blog... c'est bizarre)
moi j'ai les caractère accentué(éà ect...)
qui passe pas lol
Hmm, mon article est un peu ancien, peut être que quelque chose a changé dans l'API, je n'ai pas testé depuis bien longtemps.
Je confirme le soucis des caractères accentués, mais ça ne semble arriver que en POST. En GET, ça passe...
Bon, aussi en POST il n'y a que dans un conteneur JSON que j'ai réussi à faire marcher leur api.
J'ai essayé de préciser le charset dans les headers, ou de les encoder pour les urls, mais que dalle.
Ca vaudrait limite le coup de demander à Free ce qu'il se passe chez eux, c'est un poil étrange.
Ah, trouvé ! Encoder en utf-8 avant de formater en JSON conserve les caractères spéciaux :)
C'est du PHP, mais l'idée est là :
--------------------------------------------
$data = array(
'user' => '****', 'pass' => '***',
'msg' => utf8_encode('Texte à accents')
)
$ch = curl_init("https://smsapi.free-mobile.fr/sendmsg");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_exec($ch);