xref: /haiku/src/bin/mail_utils/mail.cpp (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
1 /*
2  * Copyright 2003-2016, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Santiago (Jacques) Lema
7  *		Jérôme Duval, jerome.duval@gmail.com
8  *		Augustin Cavalier, <waddlesplash>
9  *		Alexander G. M. Smith <agmsmith@ncf.ca>
10  */
11 
12 
13 #include <stdio.h>
14 #include <unistd.h>
15 
16 #include <Application.h>
17 #include <E-mail.h>
18 #include <String.h>
19 
20 #define APP_SIG "application/x-vnd.Haiku-mail_utils-mail"
21 
22 
23 int main(int argc, char* argv[])
24 {
25 	BApplication mailApp(APP_SIG);
26 
27 	// No arguments, show usage
28 	if (argc < 2) {
29 		fprintf(stdout,"This program can only send mail, not read it.\n");
30 		fprintf(stdout,"usage: %s [-v] [-s subject] [-c cc-addr] "
31 			"[-b bcc-addr] to-addr ...\n", argv[0]);
32 		return 0;
33 	}
34 
35 	const char *subject = "No subject";
36 	const char *cc = "";
37 	const char *bcc = "";
38 	BString to;
39 	bool verbose = false;
40 
41 	// Parse arguments
42 	for (int i = 1; i < argc; i++) {
43 		if (strcmp(argv[i], "-v") == 0)
44 			verbose = true;
45 		else if (strcmp(argv[i], "-s") == 0) {
46 			subject = argv[i+1];
47 			i++;
48 		} else if (strcmp(argv[i], "-c") == 0) {
49 			cc = argv[i+1];
50 			i++;
51  		} else if (strcmp(argv[i], "-b") == 0) {
52  			bcc = argv[i+1];
53  			i++;
54 		} else {
55 			if (to.Length() > 0)
56 				to.Append(", ");
57 			to.Append(argv[i]);
58 		}
59 	}
60 
61 	if (verbose) {
62 		fprintf(stdout, "\n");
63 		fprintf(stdout, "To:\t%s\n", to.String());
64 		fprintf(stdout, "Cc:\t%s\n", cc);
65 		fprintf(stdout, "Bcc:\t%s\n", bcc);
66 		fprintf(stdout, "Subj:\t%s\n", subject);
67 		fprintf(stdout, "\n");
68 	}
69 
70 	// Check if recipients are valid
71 	if (strcmp(to.String(), "") == 0 &&
72 		strcmp(cc, "") == 0 &&
73 		strcmp(bcc, "") == 0) {
74 
75 		fprintf(stderr, "[Error]: You must specify at least one recipient "
76 			"in to, cc or bcc fields.\n");
77 		return -1;
78 	}
79 
80 	bool isTerminal = isatty(STDIN_FILENO) != 0;
81 	if (isTerminal) {
82 		fprintf(stderr, "Now type your message.\n"
83 			"Type '.' alone on a line to end your text and send it.\n");
84 	}
85 
86 	BString body;
87 	char line[32768] = "";
88 
89 	// Read each line and collect the body text until we get an end of text
90 	// marker.  That's a single dot "." on a line typed in by the user,
91 	// or end of file when reading a file.
92 	do {
93 		if (fgets(line, sizeof(line), stdin) == NULL) {
94 			// End of file or an error happened, just send collected body text.
95 			break;
96 		}
97 
98 		if (isTerminal && strcmp(line, ".\n") == 0)
99 			break;
100 
101 		body.Append(line);
102 	} while (true);
103 
104 	if (verbose)
105 		fprintf(stdout, "\nBody:\n%s\n", body.String());
106 
107 	if (verbose)
108 		fprintf(stderr, "Sending E-mail...\n");
109 	fflush(stdout);
110 
111 	BMailMessage mail;
112 	mail.AddHeaderField(B_MAIL_TO, to.String());
113 	mail.AddHeaderField(B_MAIL_CC, cc);
114 	mail.AddHeaderField(B_MAIL_BCC, bcc);
115 	mail.AddHeaderField(B_MAIL_SUBJECT, subject);
116 	mail.AddContent(body.String(), body.Length());
117 	status_t result = mail.Send();
118 
119 	if (result == B_OK) {
120 		if (verbose)
121 			fprintf(stderr, "Message was sent successfully.\n");
122 		return 0;
123 	}
124 
125 	fprintf(stderr, "Message failed to send: %s\n", strerror(result));
126 	return result;
127 }
128