PROJET AUTOBLOG


Planet-Libre

source: Planet-Libre

⇐ retour index

Journal du hacker : Liens intéressants Journal du hacker semaine #46

lundi 16 novembre 2020 à 00:01

Pour la 46ème semaine de l'année 2020, voici 12 liens intéressants que vous avez peut-être ratés, relayés par le Journal du hacker, votre source d’informations pour le Logiciel Libre francophone !

Pour ne plus rater aucun article de la communauté francophone, voici :

De plus le site web du Journal du hacker est « adaptatif (responsive) ». N’hésitez pas à le consulter depuis votre smartphone ou votre tablette !

Le Journal du hacker fonctionne de manière collaborative, grâce à la participation de ses membres. Rejoignez-nous pour proposer vos contenus à partager avec la communauté du Logiciel Libre francophone et faire connaître vos projets !

Et vous ? Qu’avez-vous pensé de ces articles ? N’hésitez pas à réagir directement dans les commentaires de l’article sur le Journal du hacker :)

Gravatar de Journal du hacker
Original post of Journal du hacker.Votez pour ce billet sur Planet Libre.

Articles similaires

blog-libre : Terminal et puissance

dimanche 15 novembre 2020 à 10:00

What gives people feelings of power : Ce qui donne aux gens un sentiment de puissance.

Meilleur et supérieur

Il y a quelques années je me sentais meilleur que les autres simplement parce que j’utilisais le terminal. Un jour je m’étais trouvé con, les doigts légèrement au-dessus du clavier, je ne savais pas faire en ligne de commande ce que je voulais alors que ça aurait pu être résolu rapidement et facilement en quelques clics. J’étais bloqué intérieurement, je ne voulais pas m’abaisser à faire comme un simple utilisateur. J’utilisais le terminal pour me distinguer d’autrui.

Posséder ce que les autres n’ont pas ou avoir/faire mieux qu’eux permet de se démarquer, se sentir supérieur.

Étrangement j’avais besoin d’en parler, d’assumer mon erreur et le ridicule de cette situation. Je suppose que de manière inconsciente j’ai voulu ressembler et m’identifier à une élite technique, probablement une envie d’appartenance à un groupe, de reconnaissance. Maintenant j’assume bien plus/mieux mes différences et mes erreurs, je pense que ça vient avec l’âge et la confiance en soi.

Puissance et power user

J’effectue à présent une majorité d’actions en ligne de commande, je confirme efficacité, rapidité, précision (et personnalisation). Je me sens surpuissant grâce à Linux, au terminal et Bash.

Dans Humiliation, libération, volonté, puissance je disais :

Je n’ai jamais été aussi puissant qu’aujourd’hui, je suis maître de mon ordinateur, je ne suis plus esclave de mon système d’exploitation. Je réfléchis à mes besoins, l’écosystème Linux me permet d’y répondre quand Windows me limitait. Je ne suis pas libre, j’ai enlevé mes chaînes. Je ne me traîne plus avec un boulet au pied, je cours. J’apprends à être libre et responsable.

Quand je suis arrivé sur Linux, plus de chaînes, tout est ouvert et possible. Cependant la liberté implique de faire des choix, de comprendre ce qu’on fait, d’apprendre, c’est extrêmement coûteux. J’ai la chance d’être passionné, d’exercer un job de sysadmin Linux, j’ai bouffé de la connaissance. Je lance Firefox en ligne de commande, j’éteins et reboote mon pc avec des alias, je cherche et ouvre fichiers et dossiers avec des fonctions.

Le savoir est à portée de main sur Linux, on peut construire. La documentation est aussi proche que la commande man, le code est ouvert, les gens partagent, on peut suivre la correction des bugs, les issues, les releases dans les repos. Impossible sur Windows et macOS où nous sommes tributaires d’applications graphiques toutes différentes, limités au niveau configuration et modification du système.

Sur mon pc fixe, je suis en dual-boot Windows et Debian. Sur mon pc portable, chiffrement complet du disque et LVM. Grâce à Linux.

Je ne prône pas Linux pour tous, en tant que power user je témoigne de mon avancement, de ma satisfaction. Et finalement de ma puissance grâce à Linux.

Gravatar de blog-libre
Original post of blog-libre.Votez pour ce billet sur Planet Libre.

Articles similaires

miamondo : La planète Archlinux – Mise à jour du manuel d’installation

dimanche 15 novembre 2020 à 08:13

Bonjour,

Je viens tout juste de terminer la mise à jour de mon manuel d’installation d’Archlinux. Celui-ci compte cinq chapitres, dont quatre pour l’installation proprement dite. Le cinquième chapitre décrit un processus de post-installation personnalisée, lequel est bien évidemment facultatif.

J’en ai profité pour aérer la mise en page. Ce tutoriel que j’ai baptisé la planète Archlinux, est également à votre disposition en version pdf, librement téléchargeable, cela va sans dire. Si certain(e)s d’entre vous souhaitent le recevoir en version odt, n’hésitez pas à me contacter.

Il n’y a pas de grands changements depuis la dernière fois. J’ai testé l’installation dans une machine virtuelle, en l’occurrence Machines (C’est comme ça que ça s’appelle!). Il s’agit d’une application Gnome qui fonctionne plutôt bien, et le logo me plait beaucoup.

Donc je disais, j’ai testé le processus d’installation et aussi la post-installation. Verdict: Tout s’est très bien passé. Si toutefois, vous trouvez une erreur ou une approximation, merci de me le préciser en commentaires.

Bon dimanche et à bientôt.

Gravatar de miamondo
Original post of miamondo.Votez pour ce billet sur Planet Libre.

Ulrich Van Den Hekke : L'Application du confinement pour se déplacer

samedi 14 novembre 2020 à 00:00

Préambule: A cause du temps de validation du PlayStore, je publie cet article avec une semaine de retard.

Cela fait plus d'une semaine (quand j'écris ces lignes) que le re-confinement à commencé. Quand je vais courir, je dois me cantonner à 1km autour de chez moi. Mais quand je cours j'aimerais que mon téléphone intelligent me prévienne quand j'approche du rayon de 1km ou quand je le dépasse. Je ne souhaite pas avoir le nez sur une carte de mon téléphone.

Je regarde ce qui se fait. J'ai trouvé l'application suivante sur le play store : 1km. L'application m'avait l'air de répondre à mes critères mais ne fonctionnait pas lors de mon utilisation (en plus il y avait de la pub).

Une autre application 1km pourrait répondre à mon besoin mais je ne l'ai pas testé.

Beaucoup d'applications ont pour but de dessiner un cercle sur une carte.

J'ai finalement décidé d'écrire ma propre application (en plus elle sera open source).

Voici ce dont j'ai besoin:

L'application

Pour développer une application Android je vais démarrer Android Studio et commencer à développer le 1er écran. Je choisis le language Java que je maîtrise plus que le language Kotlin et le SDK Minimum de Android 6.0 pour toucher 85% des utilisateurs (si l'application peut interesser d'autres personnes).

J'imagine l'application découpée en deux parties:

Nous allons donc commencer par développer l'activité

L'activité

Je ne suis pas graphiste ni UI/UX designer. Le design de cette première interface va alors être très simple et très sobre. Un gros bouton + les différentes informations dont j'ai besoin quand l'application est démarrée :

Screenshoot page principale

Lors du démarrage de l'application, j'ai besoin que celle-ci écoute le changement, les positions de l'utilisateur afin de définir le point de départ. Comme ce service d'écoute me sera utile également pour le service, je développe une classe à coté.

ArroundLocationManager

Voici donc la classe ArroundLocationManager:

class ArroundLocationManager extends Thread {
    private static final String TAG = "ArroundLocationManager";

    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 1000;
    private static final float LOCATION_DISTANCE = 50f;

Pour commencer définissons quelques constantes: je souhaite avoir la position, tous les 50m et au maximum toutes les secondes (m'enfin quelqu'un qui fait plus de 50m en une seconde à pied est trop fort pour moi).

    private List<ArroundLocationManager.ArrroundLocationListener> listener = new ArrayList<>();

    public interface ArrroundLocationListener {
        void updateLocation(Location startLocation);
    }

    private ArroundLocationManager.LocationListener[] mLocationListeners = new ArroundLocationManager.LocationListener[]{
            new ArroundLocationManager.LocationListener(LocationManager.GPS_PROVIDER),
            new ArroundLocationManager.LocationListener(LocationManager.NETWORK_PROVIDER)
    };

    public void addListener(ArroundLocationManager.ArrroundLocationListener l) {
        listener.add(l);
    }

    private void callListener(Location location) {
        for( ArroundLocationManager.ArrroundLocationListener l : listener) {
            l.updateLocation(location);
        }
    }

Viens ensuite la définition d'un listener pour que les applications qui s'abonnent à cette classe puissent bénéficier d'un listener et recevoir des notifications lors de la mise à jour des positions.

Comme on peut le constater je fais tourner cette classe dans un thread. Lors de mon développement je me suis rendu compte que lorsque je quittais l'application, le service était tué également. Une des raisons à cela est que le service est dans le même thread que l'activité principale. L'ajout de ce thread (ainsi que d'autre chose) ont résolu le problème. (Mais il est possible que ce soit plus lié aux autres choses qu'au thread lui même).

Voici le coeur du thread:

    public void run() {
        Looper.prepare();

        initializeLocationManager();

        Looper.loop();

        // Never called, loop is killed when activity or thread stopped
        finalizeLocationManager();
    }

    private ArroundLocationManager.LocationListener[] mLocationListeners = new ArroundLocationManager.LocationListener[]{
        new ArroundLocationManager.LocationListener(LocationManager.GPS_PROVIDER),
        new ArroundLocationManager.LocationListener(LocationManager.NETWORK_PROVIDER)
    };

    public void initializeLocationManager() {
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[1]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }

        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[0]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }
    }

On utilise le service LocationManager d'android pour écouter la position de l'utilisateur. On écoute la position venant du Network qui permet d'avoir une position moins fiable mais rapide, puis celle venant du GPS permettant d'avoir une position fiable (mais lente à obtenir).

Afin d'avoir une position la plus précise aussi, je me suis inspiré du code suivant: Obtaining the Current Location. Le code en question permet de choisir entre deux positions la plus précise (entre la position NETWORK et la position GPS).

On notifie les appelants:

    private class LocationListener implements android.location.LocationListener {
        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location);
            if (isBetterLocation(location, mLocation)) {
                mLocation.set(location);
            }

            callListener(mLocation);
        }
        ...
    }

Enfin on a une méthode pour calculer les distances avec Android.:

    public static float getDistance(Location startLocation, Location lastLocation) {
        float[] results = new float[1];
        Location.distanceBetween(startLocation.getLatitude(), startLocation.getLongitude(), lastLocation.getLatitude(), lastLocation.getLongitude(), results);
        float distance = results[0];
        return distance;
    }

MainActivity

Retournons dans notre activité principale. Je passe la création du layout qui est fort simple.

Dans l'activité, nous allons commencer par implémenter la phase de création du cycle de vie de notre activité:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

Depuis Android 6.0, il faut demander à l'utilisateur la permission d'utiliser la position de l'utilisateur. Du coup on commence par demander la permission à l'utilisateur d'avoir accès à sa position2.

        requestPermissionsIfNecessary(new String[]{
                Manifest.permission.ACCESS_FINE_LOCATION,
        });

Ensuite on appelle notre location manager et on écoute les changements de positions. Pour chaque changement de position on met à jour la position et on met à jour les textes.

        locationManager = new ArroundLocationManager(this);
        locationManager.addListener((location) -> {
            if (!isMyServiceRunning(ArroundService.class)) {
                startLocation = location;
            }
            MainActivity.this.updateTextLocation();
        });
        locationManager.start();

Enfin on initialise l'IHM.

        distanceText = findViewById(R.id.distance);
        startText = findViewById(R.id.start);
        locationText = findViewById(R.id.location);

        goButton = findViewById(R.id.goButton);
        stopButton = findViewById(R.id.stopButton);
        goButton.setOnClickListener(v -> {
            setStart(true);
        });
        stopButton.setOnClickListener(v -> {
            setStart(false);
        });
        setStart(isMyServiceRunning(ArroundService.class));
        MainActivity.this.updateTextLocation();
    }

Comme le LocationManager est un thread, nous devons faire attention à repasser dans le thread de l'UI afin de mettre à jour les labels :

    public void updateTextLocation() {
        runOnUiThread(() -> {
            if (this.startLocation != null && this.runLocation != null) {
                distanceText.setText(getString(R.string.distanceLabel, (int) ArroundLocationManager.getDistance(startLocation, runLocation)));
            } else {
                distanceText.setText("");
            }
            if (this.startLocation != null) {
                startText.setText(getAddress(startLocation));
            } else {
                startText.setText("");
            }
            if (this.runLocation != null) {
                locationText.setText(getAddress(runLocation));
            } else {
                locationText.setText("");
            }
        });
    }

Pour ma part je ne connais pas la position GPS de ma maison par coeur, ni de là ou je me trouve. Cela tombe bien. Android propose une API pour geocoder une adresse. C'est à dire que l'on transforme une position en latitude, longitude en adresse lisible:

    String getAddress(Location location) {
        Geocoder geocoder;
        List<Address> addresses;

        try {
            geocoder = new Geocoder(this, Locale.getDefault());

            addresses = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1);

            if (addresses.size() > 0 && addresses.get(0).getMaxAddressLineIndex() >= 0) {
                return addresses.get(0).getAddressLine(0);
            }
            return "Unknown";
        } catch (IOException e) {
            return e.getMessage();
        }
    }

Le service

Le service est démarré par l'application et doit ensuite survivre à la fermeture de l'application. Pour cela nous allons créer un foreground service qui, contrairement aux services en tâche de fond qui sont déclenchés sur un évènement avec une durée de vie relativement courte, va tourner au premier plan en affichant une notification.

Pour démarrer le service depuis l'activité principale nous avons ajouté la méthode startServer:

    private void startServer() {
        if (!mBounded) {
            Intent mIntent = new Intent(this, ArroundService.class);
            mIntent.putExtra("startLocation", startLocation);
            ContextCompat.startForegroundService(this, mIntent);
            bindService(mIntent, mConnection, BIND_AUTO_CREATE);
        }
    }

Ce qui est important c'est la méthode startForegroundService dont le but est de démarrer le service en mode Foreground. Cette méthode a son pendant dans le service qui est startForeground. Si cette dernière n'est pas appelée dans le service une erreur sera remontée par Android.

Du coup on implémente le service et on commence par l'initialisation :

    @Override
    public void onCreate() {
        super.onCreate();
        notificationManager = new ArroundNotificationManager(this);
        locationManager = new ArroundLocationManager(this);
        locationManager.addListener(location -> {
            runLocation = location;
            callListener(location);
            notificationManager.send(getDistance());
            speakDistance();
        });
        locationManager.start();
        textToSpeech = new TextToSpeech(this, this);
    }

On démarre le notification manager qui a pour but de notifier l'utilisateur de l'existence d'un service qui tourne au 1er plan. La notification est d'ailleurs nécessaire pour un service foreground.

On écoute aussi notre ArroundLocationManager qui lors des modifications s'occupe de mettre à jour la nouvelle position et communique le changement de distance à l'utilisateur par voix et par notification.

On retrouve un callListener pour avertir l'utilisateur sur l'activité principale quand cette dernière est démarrée.

Ensuite le service démarre:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");

        PowerManager powerService = (PowerManager) getSystemService(Context.POWER_SERVICE);
        wakeLock = powerService.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ArroundService::lock");
        wakeLock.acquire();

        Bundle extras = intent.getExtras();
        Location location = (Location) extras.get("startLocation");
        if (location != null) {
            this.startLocation = location;
        }

        Notification notification = notificationManager.notifyDistance(0);
        startForeground(ArroundNotificationManager.ARROUND_ID, notification);

        return START_STICKY;
    }

Afin qu'Android et son système de gestion d'nergie ne tuent pas notre service pendant que l'on court, nous commençons par mettre un PARTIAL_WAKE_LOCK. Ensuite nous récupérons la position (sauf si nous sommes issus d'un redémarrage de l'application) et appelons la méthode startForeground avec une notification persistante que nous avons créé.

Surtout après l'acquision du Wake Lock, il est important de le relâcher lors de la fermeture (quand l'utilisateur clique sur stop):

    public void stop() {
        if (wakeLock != null) {
            if (wakeLock.isHeld()) {
                wakeLock.release();
                wakeLock = null;
            }
        }
        stopForeground(true);
        stopSelf();
    }

On en profite pour arrêter la notification (avec ̀stopForeground) et arrêter le service (avec stopSelf).

Pour lire à l'utilisateur la distance, nous utilisons android.speech.tts.TextToSpeech. Son utilisation est fort simple et se fait lors de l'appel à speakDistance:

    private void speakDistance() {
        int distance = (int) getDistance();
        if (Math.abs(lastDistance - distance) > 100) {
            int stringId;
            if (distance > 1000) {
                stringId = R.string.speaker_meters_alert;
            } else if (distance > 900) {
                stringId = R.string.speaker_meters_warn;
            } else {
                stringId = R.string.speaker_meters_info;
            }

            String text = getString(stringId, distance);

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, null);
            } else {
                textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null);
            }

            lastDistance = distance;
        }
    }

Enfin le dernier point concerne la création des notifications. Depuis la version Android O, l'application doit associer une notification à un channel. Cela permet à Android de présenter à l'utilisateur une interface avec les notifications possibles et de pouvoir désactiver/activer ces dernières au cas par cas.

AndroidNotificationManager est là pour ce but. Il va créer le channel de notification et notifier la distance à l'utilisateur.

    private static final String CHANNEL_DEFAULT_IMPORTANCE = "Running";
    public static final int ARROUND_ID = 1;

    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = context.getString(R.string.channel_name);
            String description = context.getString(R.string.channel_description);
            NotificationChannel channel = new NotificationChannel(CHANNEL_DEFAULT_IMPORTANCE, name, NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription(description);
            NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
    }

    public Notification createNotification(float distance) {
        Intent notificationIntent = new Intent(context, MainActivity.class);
        PendingIntent pendingIntent =
                PendingIntent.getActivity(context, 0, notificationIntent, 0);

        return new NotificationCompat.Builder(context, CHANNEL_DEFAULT_IMPORTANCE)
                .setContentTitle(context.getText(R.string.notification_title))
                .setContentText(context.getString(R.string.notification_message, (int) distance))
                .setSmallIcon(android.R.drawable.ic_menu_mylocation)
                .setContentIntent(pendingIntent)
                .build();
    }

    public void notifyDistance(float distance) {
        Notification n = this.createNotification(distance);
        NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
        notificationManager.notify(ARROUND_ID, n);
    }

Il est important lors de l'appel à notifyDistance de toujours utiliser le même identifiant de notification afin que cette dernière soit remplacée (et non ajouté). Cela permet de mettre à jour le contenu de la notification.

Pour finir

Pour finir je suis content d'avoir développé cette application qui n'est pas exempte de bug, mais qui m'a pris très peu de temps de développement.

Vous pouvez retrouver le code source sur Github: phoenix741/1kmarround et sur le PlayStore (à ce jour l'application n'a pas encore été validé dans les stores et n'est donc pas disponible).

Le plus long dans ce développement aura été:


  1. Une activité est l'équivalent d'un écran dans Android. 

  2. Pour demander les permissions je me suis basé sur le code suivant:

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        ArrayList permissionsToRequest = new ArrayList<>();
        for (int i = 0; i < grantResults.length; i++) {
            permissionsToRequest.add(permissions[i]);
        }
        if (permissionsToRequest.size() > 0) {
            ActivityCompat.requestPermissions(this, permissionsToRequest.toArray(new String[0]), REQUEST_PERMISSIONS_REQUEST_CODE);
        }
    }
    
    private void requestPermissionsIfNecessary(String[] permissions) {
        ArrayList permissionsToRequest = new ArrayList<>();
        for (String permission : permissions) {
            if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
                // Permission is not granted
                permissionsToRequest.add(permission);
            }
        }
        if (permissionsToRequest.size() > 0) {
            ActivityCompat.requestPermissions(this, permissionsToRequest.toArray(new String[0]), REQUEST_PERMISSIONS_REQUEST_CODE);
        }
    }
    

Gravatar de Ulrich Van Den Hekke
Original post of Ulrich Van Den Hekke.Votez pour ce billet sur Planet Libre.

Simon Vieille : Mail RSS : transformer des mails en flux RSS

jeudi 12 novembre 2020 à 18:04

J'essaye de plus en plus de réduire le volume de mails que je reçois. Du coup, quand une newsletter m'intéresse et que les auteurs ne fournissent pas de flux RSS, cela me donne un prétexte pour écrire un nouveau projet : Mail RSS.

Comment ça marche ?

L'idée est assez simple : en utilisant les alias de mail dans Postfix, on peut faire en sorte qu'un mail qui arrive sur le serveur soit traité par une commande. J'ai décidé de rediriger les mails dans un répertoire précis du serveur et je demande à Mail RSS de les lire et de les importer.

Prenons la newsletter de TechTrash comme exemple.

Configuration du serveur de mail

Il faut ajouter un alias qui va générer des fichiers.

techtrash: "| cat > /var/lib/mailrss/techtrash-$(date +%s) && chmod o+rw /var/lib/mailrss/techtrash-$(date +%s)"

Au préalable, j'ai créé le répertoire /var/lib/mailrss et je me suis assuré que mon application pouvait lire et écrire dedans, de même que Postfix (nobody:nogroup).

Configuration de l'application

On doit générer un mailing pour TechTrash. Quand on va importer les mails de TechTrash, on pourra les associer au mailing via son identifiant (ID). On pourra ensuite accéder au flux RSS via le lien généré à sa création. Évidement, on peut créer autant de mailing que l'on veut, les modifier et les supprimer.

$ php bin/console mailing:new "TechTrash"
$ php bin/console mailing:list
 ------------ -------------------------------------- ------------------------------------------------------------------------ --------------------- --------------------- 
  Label        ID                                     Feed                                                                     Created at            Updated at           
 ------------ -------------------------------------- ------------------------------------------------------------------------ --------------------- --------------------- 
  Tech Trash   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   https://exemple.fr/mailing/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/rss   2020-11-12 13:37:00   2020-11-12 13:37:00  
 ------------ -------------------------------------- ------------------------------------------------------------------------ --------------------- --------------------- 

Enfin, il faut un script qui va traiter les fichiers de /var/lib/mailrss en les important dans le mailing correspondant et qui les supprime du serveur.

#!/bin/sh

cd "/path/to/exemple.fr"

find /var/lib/mailrss -name "techtrash-*" | while read MAIL_FILE; do
    cat "MAIL_FILE" | php bin/console mail:import xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

    rm "MAIL_FILE"
done

Quand un mail est importé, les données récupérées sont :

Toutes ces données seront accessibles à la consultation.

L'application s'appuie sur Symfony (en version de développement) et le code est totalement libre 😄

Gravatar de Simon Vieille
Original post of Simon Vieille.Votez pour ce billet sur Planet Libre.