[smtplib] problème pour envoyer un mail
Résoluartemis-037 Messages postés 57 Date d'inscription Statut Membre Dernière intervention -
Bonjour,
J'ai écrit un programme pour récupérer les logs de connexion sur mon serveur par mail
import smtplib, ssl import os import subprocess os.system('sudo sh -c "> /var/log/apache2/access.log"') def envoi_mail(contenu): smtp_address = 'smtp.gmail.com' smtp_port = 465 email_address = '*******************' email_password = '********************' email_receiver = '********************' context = ssl.create_default_context() with smtplib.SMTP_SSL( smtp_address, smtp_port, context=context ) as server: server.login(email_address, email_password) server.sendmail(email_address, email_receiver, contenu) envoi_mail('demarage') run = True while run: v = subprocess.check_output( ['sudo', 'cat', '/var/log/apache2/access.log'] ).decode('utf-8', errors="backslashreplace").split('\n') if v != ['']: print(v) envoi_mail('nouvelle connection' + str(v)) os.system('sudo sh -c "> /var/log/apache2/access.log"')
Mais le problème, c'est que ce code envoie bien le mail avec démarrage mais lorsque je me connecte je reçois un mail vide au lieu de "nouvelle connection...")
J'attend vos réponses avec impatience
- Mail python.net
- Publipostage mail - Accueil - Word
- Windows live mail - Télécharger - Mail
- Créer une adresse mail hotmail - Guide
- Comment télécharger un mail - Guide
- Cegetel mail ✓ - Forum Mail
2 réponses
Bonjour,
Chaque page Web peut entraîner des dizaines de requêtes HTTP à cause des CSS, JS et autres ressources incluses, cela risque de générer un grand nombre de connexions vers le serveur SMTP de Gmail, avec à chaque fois l'établissement d'une nouvelle session TLS et une authentification par utilisateur / mot de passe, et donc des performances médiocres, en plus de risquer de se heurter à des limites de connexion. Je parle là des "connexions" (au niveau TCP/TLS), mais Gmail applique aussi des limites journalières sur les e-mails envoyés. Si tu souhaites recevoir des notifications pour chaque requête HTTP, même si c'est une idée un peu farfelue, je te conseille de voir du côté de Gotify ou Ntfy. Peux-tu nous dire l'objectif final de ton projet ? Il existe sûrement une solution plus adaptée et pratique.
La deuxième chose qui m'interpelle, c'est que tu utilises des commandes shell pour lire/écrire dans les fichiers : pourquoi ne pas utiliser les fonctions Python appropriées ?
La façon dont tu surveilles le registre est loin d'être optimale : avec une boucle infinie sans aucun délai, sans aucune pause, de quoi faire grimper le CPU inutilement.
Je pense que la meilleure solution serait de configurer Apache afin de rediriger les logs vers ton programme et non vers un fichier. De cette façon, plus besoin de surveiller le fichier, ton programme est appelé à chaque nouvelle entrée. https://httpd.apache.org/docs/2.4/logs.html#piped
Si tu veux continuer avec le fichier access_log habituel, il y a des façons plus intelligentes de surveiller les changements, par exemple avec https://pypi.org/project/watchfiles/ sinon pourquoi pas avec un délai de quelques secondes entre chaque vérification.
Pour le problème que tu rencontres, c'est surprenant que tu reçoives un mail vide, il devrait au minimum contenir "nouvelle connection". Quel est le résultat affiché par la ligne 26 ? Si dans la fonction "envoi_mail" tu affiches la variable "contenu" ?
Bonjour,
J'ignore volontairement toutes les considérations liées à l'envoi d'email puisque tu parviens à en envoyer, mais sur le plan pratique, je partage l'avis d'avion-f16 (voir #1), tu risques d'en recevoir beaucoup si tu en envoies au moindre changement apporté à ce fichier de log :-)
Je signale par ailleurs qu'apache offre de base des mécanismes pour envoyer des emails à son administrateur sous certaines conditions (voir par exemple cette discussion).
Si malgré toutes ces réserves, tu souhaites poursuivre, l'idéal serait que ton programme python utilise watchdog. En s'inspirant de cette réponse, tu pourrais écrire :
import sys import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler class MyHandler(FileSystemEventHandler): def __init__(self, path): super().__init__() self.path = path self.last_content = None with open(path, "r") as f: self.last_content = f.read() def on_modified(self, event): if not event.is_directory: with open(event.src_path, "r") as f: content = f.read() if ( self.last_content is not None and content != self.last_content ): change = content[len(self.last_content):] self.notify_change(change) self.last_content = content def notify_change(self, change): print(self.path, ":", change, end="") if __name__ == "__main__": path = sys.argv[1] if len(sys.argv) > 1 else '.' event_handler = MyHandler(path) observer = Observer() observer.schedule(event_handler, path, recursive=False) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()
Utilisation : en admettant que le script python s'appelle monitor.py :
python3 monitor.py /var/log/apache2.log
Il ne reste qu'à adapter la méthode notify_change pour y créer un email dont le corps de message contiendra le contenu de la variable change.
Bonne chance
Bonjour,
Comme je l'ai expliqué dans mon message :
Il ne reste qu'à adapter la méthode notify_change pour y créer un email dont le corps de message contiendra le contenu de la variable change.
Donc quelque chose du genre :
import smtplib import ssl # ... class MyHandler(FileSystemEventHandler): # ... def notify_change(self, change): smtp_address = 'smtp.gmail.com' smtp_port = 465 email_address = '*******************' email_password = '********************' email_receiver = '********************' context = ssl.create_default_context() with smtplib.SMTP_SSL( smtp_address, smtp_port, context=context ) as server: server.login(email_address, email_password) server.sendmail( email_address, email_receiver, change ) # ...
Ensuite il y a plusieurs manières d'améliorer ce code.
- Concernant le design, on pourrait imaginer que l'envoi de l'email soit implémenté dans une classe dédiée, et que ton handler prenne une instance de cette classe en paramètre.
- Concernant la sécurité, il faut éviter de stocker un mot de passe en clair dans du code. Idéalement, ton programme devrait le lire depuis un fichier avec des droits restreints.
Bonne chance
Pour tes problèmes de connexion ssh, je ne peux que t'encourager à mettre en place une clé ssh et désactiver l'authentification par mot de passe (voir ici). Je ne m'étends pas plus car ce n'est pas le sujet ici. Si tu rencontres des difficultés, je t'invite à ouvrir un nouveau fil de discussion sur le forum Linux. Merci également de soigner l'orthographe dans tes futurs messages.
Merci pour ta réponse. Si par contenu, tu parles de la variable v, il y est bien écrit les log, et non, il n'y a même pas "nouvelle connexion" dans le mail.
Je vais rajouter un délai de 5 sec entre chaque actualisation, même si c'est le seul programme, qui tourne sur mon serveur pour le moment.