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
23int 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