您的位置:首页 > 大数据 > 人工智能

用GTK+编写邮件客户端

2012-06-23 00:00 387 查看
效果:

正确发送邮件,状态栏显示OK。



发送邮件错误,状态栏显示相应的状态信息。



代码:

Mail-Client: Mail-Client.c
gcc Mail-Client.c -DDEBUG=0 -o Mail-Client `pkg-config --cflags --libs gtk+-2.0`


/* Mail-Client: fork+exec+pipe+redirection */
#include <gtk/gtk.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#define MAX_RECV_BUF_LEN 1024
#if DEBUG
#define PDEBUG(fmt, args...) printf(fmt, ##args)
#else
#define PDEBUG(fmt, args...)
#endif

struct EntryPack
{
GtkWidget *mToEntry;
GtkWidget *mSubjectEntry;
GtkTextBuffer *mMessageBuffer;
GtkStatusbar *mStatusBar;
};

/**
* func: send_email
* @return : 0 for success; -1 for failure;
* @errmsg: if -1 is returned, errmsg contains the corresponding error msg
*
* this function makes use of fork, exec, dup, pipe to create the following structure
* Mail-Client -- pipe_to_mail --> mail command
* mail command -- pipe_from_mail --> Mail-Client
**/
int send_email(const char *to, const char *subject, const char *message, char *errmsg)
{
int pipe_to_mail[2], pipe_from_mail[2];
int pid;
int ret;

assert(errmsg != NULL);
ret = pipe(pipe_to_mail);
assert(ret == 0);
ret = pipe(pipe_from_mail);
assert(ret == 0);

pid = fork();
if (pid < 0)
{
fprintf(stderr, "fork failed: code=%d (%s) \n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid == 0)	/* in child process */
{
/* receive message from pipe_to_mail, execute mail command, return result to parent using pipe_from_mail */
PDEBUG("In Child Process\n");
PDEBUG("to: %s \n", to);
PDEBUG("subject: %s\n", subject);
PDEBUG("message: %s\n", message);
/* redirect its standard input from pipe[0] */
close(0);
dup(pipe_to_mail[0]);
close(pipe_to_mail[1]);
close(pipe_to_mail[0]);
/* redirect its standard output to pipe[1] */
close(2);
dup(pipe_from_mail[1]);
close(pipe_from_mail[0]);
close(pipe_from_mail[1]);

execlp("mail", "mail", "-s", subject, to, NULL);
exit(EXIT_FAILURE);
}
else			/* in parent process */
{
/* send message to child process */
close(pipe_to_mail[0]);
int msg_len = strlen(message);
int count = 0;
while (count < msg_len)
{
ret = write(pipe_to_mail[1], message, msg_len-count);
if (ret < 0)
{
fprintf(stderr, "unexpected error in write: code=%d (%s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
else
{
PDEBUG("write %d bytes to pipe\n", ret);
count += ret;
PDEBUG("msg_len = %d, count = %d \n", msg_len, count);
}
}
close(pipe_to_mail[1]); /* write finished */
/* receive result from its child process: mail */
close(pipe_from_mail[1]); /* close the write end */
char buf[MAX_RECV_BUF_LEN] = {0};
ret = read(pipe_from_mail[0], buf, sizeof(buf));
close(pipe_from_mail[0]);
/* wait for child process to exit */
int status;
wait(&status);
PDEBUG("child process exited with status: %d\n", status);
/* if status != 0, print out the contents from mail */
if (strlen(buf) != 0)
{
//			fprintf(stderr, "error in sending mail: %s\n", buf);
sprintf(errmsg, "Error! %s", buf);
return -1;
}
else
{
return 0;
}
}
}

void closeApp(GtkWidget *window, gpointer data)
{
gtk_main_quit();
}

void button_send_clicked(GtkWidget *button, gpointer data)
{
GtkTextBuffer *buffer = ((struct EntryPack*)data) -> mMessageBuffer;
GtkWidget *toEntry = ((struct EntryPack*)data) -> mToEntry;
GtkWidget *subjectEntry = ((struct EntryPack*)data) -> mSubjectEntry;
GtkStatusbar *statusbar = ((struct EntryPack*)data) -> mStatusBar;
/* get message */
GtkTextIter start, end;
gtk_text_buffer_get_bounds(buffer, &start, &end);
char *msg;
msg = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
PDEBUG("%s\n", msg);
/* get recipient's address */
const char *to = gtk_entry_get_text(GTK_ENTRY(toEntry));
/* get subject */
const char *subject = gtk_entry_get_text(GTK_ENTRY(subjectEntry));
/* send email */
gtk_statusbar_push(statusbar, 0, "Sending Mail ...");
char errmsg[256] = {0};
int ret = send_email(to, subject, msg, errmsg);
if (ret == 0)
{
/* update statusbar: success */
PDEBUG("OK\n");
gtk_statusbar_push(statusbar, 0, "OK");
}
else
{
/* update statusbar: failed */
PDEBUG("Error! %s\n", errmsg);
gtk_statusbar_push(statusbar, 0, errmsg);
}
free(msg);
}

void button_clear_clicked(GtkWidget *button, gpointer data)
{
GtkTextBuffer *buffer = ((struct EntryPack*)data) -> mMessageBuffer;
GtkWidget *toEntry = ((struct EntryPack*)data) -> mToEntry;
GtkWidget *subjectEntry = ((struct EntryPack*)data) -> mSubjectEntry;
GtkStatusbar *statusbar = ((struct EntryPack*)data) -> mStatusBar;
GtkTextIter start, end;
gtk_text_buffer_get_bounds(buffer, &start, &end);
gtk_text_buffer_delete(buffer, &start, &end);
gtk_entry_set_text(GTK_ENTRY(toEntry), "");
gtk_entry_set_text(GTK_ENTRY(subjectEntry), "");
gtk_statusbar_push(statusbar, 0, "");
}

void button_quit_clicked(GtkWidget *button, gpointer data)
{
gtk_main_quit();
}

int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *label_to, *label_subject, *label_message;
GtkWidget *entry_to, *entry_subject;
GtkTextBuffer *messageBuffer;
GtkWidget *messageView;
GtkWidget *button_send, *button_clear, *button_quit;
GtkWidget *statusbar;
GtkWidget *hbox1, *hbox2, *hbox3;
GtkWidget *vbox;
struct EntryPack pack;

gtk_init(&argc, &argv);

/* create main window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Mail Client");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
g_signal_connect(GTK_OBJECT(window), "destroy",
GTK_SIGNAL_FUNC(closeApp), NULL);

/* create label */
label_to = gtk_label_new("To:");
label_subject = gtk_label_new("Subject:");
label_message = gtk_label_new("Message:");
/* create entry */
entry_to = gtk_entry_new();
entry_subject = gtk_entry_new();
/* create message view and message buffer */
messageView = gtk_text_view_new();
messageBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(messageView));
/* pack entry */
pack.mToEntry = entry_to;
pack.mSubjectEntry = entry_subject;
pack.mMessageBuffer = messageBuffer;
/* create button */
button_send = gtk_button_new_with_label("Send");
button_clear = gtk_button_new_with_label("Clear");
button_quit = gtk_button_new_with_label("Quit");
/* associate button callbacks */
g_signal_connect(GTK_OBJECT(button_send), "clicked",
GTK_SIGNAL_FUNC(button_send_clicked), &pack);
g_signal_connect(GTK_OBJECT(button_clear), "clicked",
GTK_SIGNAL_FUNC(button_clear_clicked), &pack);
g_signal_connect(GTK_OBJECT(button_quit), "clicked",
GTK_SIGNAL_FUNC(button_quit_clicked), NULL);
/* create status bar */
statusbar = gtk_statusbar_new();
/* pack statusbar */
pack.mStatusBar = GTK_STATUSBAR(statusbar);
/* organize layout */
hbox1 = gtk_hbox_new(FALSE, 5);
hbox2 = gtk_hbox_new(FALSE, 5);
hbox3 = gtk_hbox_new(FALSE, 5);
vbox = gtk_vbox_new(FALSE, 10);

gtk_box_pack_start(GTK_BOX(hbox1), label_to, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox1), entry_to, TRUE, TRUE, 5);

gtk_box_pack_start(GTK_BOX(hbox2), label_subject, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox2), entry_subject, TRUE, TRUE, 5);

gtk_box_pack_start(GTK_BOX(hbox3), button_send, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox3), button_clear, TRUE, TRUE, 5);
gtk_box_pack_start(GTK_BOX(hbox3), button_quit, TRUE, TRUE, 5);

gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 1);
//	gtk_box_pack_start(GTK_BOX(vbox), label_message, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(vbox), messageView, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox), hbox3, FALSE, FALSE, 1);
gtk_box_pack_start(GTK_BOX(vbox), statusbar, FALSE, FALSE, 1);

gtk_container_add(GTK_CONTAINER(window), vbox);

gtk_widget_show_all(window);
gtk_main();

return 0;

}


后记:

这是第一个版本,实现了邮件的正确发送。

目前版本中,使用了mail这个命令处理后台实际发送邮件的任务。以后要手动进行SMTP协议的处理。

参考资料:

gtk-demo (这个命令很nb,有示例,有源码)

gtk的devhelp(这个应用很强大,类似微软的MSDN)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息