Salut,
Je me suis programmé mon notifieur d'arrivée d'e-mail.
personnellement j'en suis très satisfait.
j'utilise les sockets openssl imap pour récupérer les entêtes d'e-mail,
libnotify pour envoyer les notifications et dunst pour les afficher.
Le bug n'est pas systématique, mais relativement fréquent, même avec un boot récent.
Pour l'instant je règle le problème avec un reboot.
gcc --version
gcc (GCC) 5.1.0
Code : Tout sélectionner
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <libnotify/notify.h>
#include <glib.h>
typedef struct {
int socket;
SSL *sslHandle;
SSL_CTX *sslContext;
} connection;
#include "imapssl.h"
typedef struct {
int nb;
int recents;
int nonlu;
int last_uid;
int last_uidprev;
char *boxname;
connection *c;
} Mailbox;
typedef struct {
char date[19];
char de[50];
char sujet[50];
} Headermsg;
#define SERVER "212.27.48.2"
#define PORT 993
#define LOGIN "001 LOGIN %s %s\r\n"
#define SELECTINBOX "002 SELECT INBOX\r\n"
#define FETCHHEADER "004 FETCH %i body[header]\r\n"
#define READSIZE 1024
#define NOTIFICON "mail-unread"
#define APPNAME "imapssl"
static const char *boxnames[] = {"box01","box02","box03","box04"};
static Mailbox boxes[sizeof(boxnames) / sizeof(boxnames[0])];
connection *c;
int tcpConnect()
{
int error, handle;
struct hostent *host;
struct sockaddr_in server;
host = gethostbyname(SERVER);
handle = socket (AF_INET, SOCK_STREAM, 0);
if (handle == -1) {
perror ("Socket");
handle = 0;
}
else {
server.sin_family = AF_INET;
server.sin_port = htons (PORT);
server.sin_addr = *((struct in_addr *) host->h_addr);
bzero (&(server.sin_zero), 8);
error = connect(handle, (struct sockaddr *) &server, sizeof (struct sockaddr));
if (error == -1) {
perror ("Connect");
handle = 0;
}
}
return handle;
}
connection *sslConnect(void)
{
connection *c;
c = malloc(sizeof (connection));
c->sslHandle = NULL;
c->sslContext = NULL;
c->socket = tcpConnect ();
if (c->socket) {
SSL_load_error_strings (); // Register the error strings for libcrypto & libssl
SSL_library_init (); // Register the available ciphers and digests
// New context saying we are a client, and using SSL 2 or 3
c->sslContext = SSL_CTX_new (SSLv23_client_method ());
if (c->sslContext == NULL)
ERR_print_errors_fp (stderr);
c->sslHandle = SSL_new (c->sslContext); // Create an SSL struct for the connection
if (c->sslHandle == NULL)
ERR_print_errors_fp (stderr);
if ( !SSL_set_fd (c->sslHandle, c->socket) ) // Connect the SSL struct to our connection
ERR_print_errors_fp (stderr);
if (SSL_connect (c->sslHandle) != 1) // Initiate SSL handshake
ERR_print_errors_fp (stderr);
}
else {
perror ("Connect failed");
}
return c;
}
void sslDisconnect(connection *c) // Disconnect & free connection struct
{
if (c->socket)
close (c->socket);
if (c->sslHandle) {
SSL_shutdown (c->sslHandle);
SSL_free (c->sslHandle);
}
if (c->sslContext)
SSL_CTX_free (c->sslContext);
free (c);
}
char *sslRead(connection *c) // Read all available text from the connection
{
const int readSize = READSIZE;
char *rc = NULL;
int received, count = 0;
char buffer[READSIZE];
if (c) {
while (1) {
if (!rc)
rc = malloc (readSize * sizeof (char) + 1);
else
rc = realloc (rc, (count + 1) * readSize * sizeof (char) + 1);
received = SSL_read(c->sslHandle, buffer, readSize);
buffer[received] = '\0';
if (received > 0) strcat (rc, buffer);
if (received < readSize) break;
count++;
}
}
return rc;
}
void sslWrite(connection *c, char *text) // Write text to the connection
{
if (c)
SSL_write(c->sslHandle, text, strlen (text));
}
/*------------------------------*/
/* dessous, c'est les miennes */
/*------------------------------*/
int connect_one_box(char *login, Mailbox *bx)
{
char *r1;
bx->c = sslConnect();
r1 = sslRead(bx->c);
sslWrite(bx->c, login);
r1 = sslRead(bx->c);
return strlen(r1) > 250;
}
int get_uid(Mailbox *bx)
{
char *r1, *r2;
int i=0;
sslWrite(bx->c, SELECTINBOX);
r1 = sslRead(bx->c);
r1 = strchr(r1, '*');
r2 = strchr(r1, '\r');
while ( r2 ) {
r2[0] = '\0';
switch ( i++ ) {
case 0 : bx->nb = atoi(r1+2); break;
case 1 : bx->recents = atoi(r1+2); break;
case 2 : if ( strstr(r1, "[UNSEEN")) bx->nonlu = 1; break;
case 3 : if ( strstr(r1, "[UIDNEXT")) {
*strchr(r1, ']') = '\0';
bx->last_uid = atoi(r1+14);
*r1 = '\0';
}
break;
case 4 : if ( strstr(r1, "[UIDNEXT")) {
*strchr(r1, ']') = '\0';
bx->last_uid = atoi(r1+14);
*r1 = '\0';
}
break;
}
r1 = r2+2;
r2 = strchr(r1, '\r');
}
if ( bx->last_uidprev == 0 )
bx->last_uidprev = bx->last_uid;
return bx->last_uidprev != bx->last_uid;
}
int get_header(Mailbox *bx, Headermsg *msg)
{
char fetch[128];
char *r1, *r2;
sprintf(fetch, FETCHHEADER, bx->nb);
sslWrite(bx->c, fetch);
r1 = sslRead(bx->c);
r2 = strchr(r1, '\r');
while ( r2 ) {
r2[0] = '\0';
switch ( r1[0] ) {
case 'D' : if ( strncmp(r1, "Date:", 5) == 0 ) {
*strrchr(r1, ':') = '\0';
sprintf(msg->date, "%s", r1+11);
}
break;
case 'F' : if ( strncmp(r1, "From:", 5) == 0 ) sprintf(msg->de, "%s", r1+6);
break;
case 'S' : if ( strncmp(r1, "Subje", 5) == 0 ) sprintf(msg->sujet, "%s", r1+9);
break;
}
r1 = (char *) r2+2;
r2 = strchr(r1, '\r');
}
bx->last_uidprev = bx->last_uid;
return 0;
}
int notify_send(Mailbox *bx, Headermsg *msg)
{
char head[128];
char body[128];
NotifyNotification *n;
notify_init("imapssl");
sprintf(head, "%s (%s)\n", bx->boxname, msg->date);
sprintf(body, "%s\n%s", msg->de, msg->sujet);
//printf("[[%i-%s]]", strlen(body), body);
n = notify_notification_new(head, body, NOTIFICON);
notify_notification_set_app_name(n, APPNAME);
if (!notify_notification_show(n, NULL)) {
g_error("Failed to send notification.\n");
return 1;
}
g_object_unref(G_OBJECT(n));
return 0;
}
int main (int argc, char **argv)
{
char *login = "lemien" ;
Headermsg msg;
int nbboxes = sizeof(boxnames) / sizeof(boxnames[0]);
int go = 1;
int i;
while ( go ) {
for(i=0;i<nbboxes;i++) {
boxes[i].boxname = (char *) boxnames[i];
sprintf(login, LOGIN, boxnames[i], zzzy);
if ( connect_one_box(login, &boxes[i]) && get_uid(&boxes[i]) )
{
get_header(&boxes[i], &msg);
notify_send(&boxes[i], &msg);
}
sslWrite(boxes[i].c, "999 LOGOUT\r\n");
sslDisconnect(boxes[i].c);
}
sleep(300); // 5mn
}
return 0;
}
// vim: ts=4 sw=4