Sending emails in C++ & logical error

1st: Logical Error:

cout << "Subscribes? " << endl;
getline (cin, subscribes);
cout << "Unsubscribes?" << endl;
getline (cin, unsubscribes);


For some strange reason if I use cin >> subscribes and cin >> unsubscribes in the above cases instead of a parameter in getline() as shown above I get to enter values for both subscribes or unsubscribes. Using getline() as shown above only allows me to input data for unsubscribes and skips subscribes completely.

I'm using cin and cout from the iostream library.
and getline from the string library

How can I get to input a line of data for both subscribes and unsubscribes?

/////////////////////

2nd: Sending emails in C++

What's the best way of doing this? Is there a library I can install or already exists with functions or what not? Or can I hook into a program somehow that does this?

like:
FILE * mFile = fopen("/usr/bin/mail ~'"+message+"' -s '"+subject+"' '"+email+"' ", "w");
fclose(mailer)


where message, subject and email are string objects

Because the above won't work. I get the following error:
MailMngr.C:42: error: cannot convert ‘std::basic_string<char, std::char_traits<char>, std::allocator<char> >’ to ‘const char*’ for argument ‘1’ to ‘FILE* fopen(const char*, const char*)’

I'm used to programming in java so the compiler errors like this confuse me.
Last edited on
Try the .c_str() method of your string variables in the fopen parameters. fopen appears to be expecting a const char *, not a std::string (which is a typedef for std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
1st: I believe it's because getline() does not remove the last \r \n or \whatever you have on the end of your line. You will need to use cin.ignore() or something similar.
try using flush stream between two "cin" statements
hey for your second question, can you post your code so i can compile and see what's wrong with your code....
I tried cin.ignore() btw. Which let me input values for both subscribes and unsubscribes but only stored the subscribes value. This is the opposite to what happened before only this time I can input unsubscribes and nothing is stored.

the code for the second bit is this:

#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <exception>
using namespace std;

string message ("TEST");
string subject ("MailMngr Message");
string email ("xxxx@gmail.com");

try {
FILE * mFile = fopen("/usr/bin/mail ~'"+message+"' -s '"+subject+"' '"+email+"', "w");
fprintf(mFile, "Hello %s,\nYour job was completed successfully.\n", "");
fclose(mFile);
}
catch (exception& e)
{
cout << "Exception occured!" << e.what() << "\n";
}
try this....

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <exception>

using namespace std;

string message ("TEST");
string subject ("MailMngr Message");
string email ("xxxx@gmail.com");
int main()
{
	try {
		char fileName[50];
		sprintf(fileName,"/usr/bin/mail ~' %s ' -s ' %s ' ' %s '",message.c_str(),subject.c_str(),email.c_str());

		//FILE * mFile = fopen("/usr/bin/mail ~'"+message+ "' -s '" + subject + "' '" +email+"' ", "w");
		FILE * mFile = fopen(fileName, "w");
		fprintf(mFile, "Hello %s,\nYour job was completed successfully.\n", "");
		fclose(mFile);
	}
	catch (exception& e)
	{
		cout << "Exception occured!" << e.what() << "\n";
	}
	return 0;
}
Issue1: Use cin.getline() instead of getline(cin, string);

Issue2: use exec(); instead of trying to open the mail executable. I'd highly suspicious of using a FILE* to open an executable to execute it. I'm also surprised your using a C method of File I/O and not the C++ method.
using cin.getline() resulted in an error dump for me:

MailMngr.C:33: error: no matching function for call to ‘std::basic_istream<char, std::char_traits<char> >::getline(std::string&)’
/usr/include/c++/4.3/istream:598: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize, _CharT) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/include/c++/4.3/istream:409: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::getline(_CharT*, std::streamsize) [with _CharT = char, _Traits = std::char_traits<char>]

maxchirag's optimisation of the file interactions prevented compile errors occuring for that part of the code, only i'm not getting any email coming through at my end. This could possibly be due to my incorrect usage of the mail program.
Hello Poyntz,

I have just tried to correct the code to avoid the compiler errors (as you said before) and doesn't care for the logical stuff, if you want me to also look into that, you have to post code and what do you want a program to do (your task)....

what i understood from your previous post is, you want some file operations with string objects, and you are getting compiler errors, that's it!

by the way, opening mail binary file in this way is not a good option, try using some other methods, for e.g exec().
Last edited on
basically I want the program to get the inputs from the input streams, ie, cin. store them as vars, and then post them to my email. I've included comments to try to explain what I'm doing.

As can be seen I've got the cout streams to display the values of the vars. - This is not intended to be part of the program, I've just included this to ensure that the data is being stored correctly, which it doesn't seem to be. So even if I do get the code to send emails to me it won't include the data that I want.

Please excuse my dismal attempt to use exec(). I'm really new to C++ and without API documentation and an inability to find information on the method using searches, plus an inability to understand what the compiler is trying to tell me I can't figure out what I'm doing wrong, or how I could be using it correctly.

P.S: I did borrow a book from the library but it's failing to tell me anything much new that I haven't learned from my experience with java (ie, mostly logical talk and not much on the libraries and their methods and how to use them)

My code is below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <exception>
#include <unistd.h>
using namespace std;

int main()
{
//Declaring vars to be used
string subject ("Mail Manager Message");
string message ("test");
string email ("xxxx@gmail.com");
string subscribes ("");
string unsubscribes ("");
char grp ('');
string group ("");

//Make a choice, A or B?
cout << "A: mudc-com or B: mudc-members?" << endl;
cin >> grp;

//if A is typed store mudc-com as group. else for B mudc-members as group.
//if anything else it typed explain that that's not right and quit the program
if (grp == 'A')
	group = "mudc-com";
else if (grp == 'B')
	group = "mudc-members";
else
{
	cout << "You must enter either A or B" << endl;
	exit(0);
}

//Store the string user types as a subscribes and an unsubscribes string
// (these have to be separate for some extension i'm going to do to the program later.
// - this extension will be mostly logical and won't require much knowledge of C++ itself so I should
// be fine working this part out
cout << "Subscribes? " << endl;
getline (cin, subscribes);                   //cin.getline(subscribes); - should I be using this somehow?
cout << "Unsubscribes?" << endl;
getline (cin, unsubscribes);

// Display what's stored to me so I can verify it's been stored correctly
cout << "Member Group: "+group << endl; 
cout << "Subscribed are: "+subscribes << endl; 
cout << "Unsubscribed are: "+unsubscribes << endl;

// This is in a Try/Catch block because that is the way you do file interactions in java
// not sure if the same logic needs to apply to C++, but it's always good to receive stack dumps for 
// problems anyhow
/**
// Basically this should send the message to the email in the email var at the top of the page. 
// The message var data at the top of the page should be included in this, as should the subject var 
// data.
// I'm using /usr/bin/mail as the program for this because it's the only mail prog i know that can send 
// emails from the command line. If there's a better way to do this ie, better program to use or if there 
// need not be an external program used, feel free to show this as well.
**/
try {
	FILE *mFile = execv(NULL, "/usr/bin/mail ~' %s ' -s ' %s ' ' %s '",message.c_str(),subject.c_str(),email.c_str());
        fprintf(mFile, "Hello %s,\nYour job was completed successfully .\n", "");
	fclose(mFile);
}

// Catch any thrown exceptions...
catch (exception& e)
{
	cout << "Exception occured!" << e.what() << "\n"; 
}
return 0;
}
Last edited on
Forget about the FILE*. That's used for OPENING files for reading/writing. Your trying to EXECUTE a file.

If your having issues with your getLine(cin, var) statements. Try putting a cin.clear(); before it.
Hello,

i tried to understand what you expect from your program, and obviously as Zaita said, fopen is not a solution to execute a program. always remember fopen is for reading and writing file itself, obviously you should not read the mail binary file to send mail. you need to execute that file, and for that you can use some version of system call execl to do that..... execl basically forks the child process and load the content of the file you mention for execution(with your argument) i propose another solution to do that(that you can see in my example),

okay, that was first thing(C++ stuff till execution of program), but the final aim of the program is to send a mail, for that you need to configure the mail transfer agent and that is not C++, that is linux, you can read the manual for how to configure sendmail, i have never used sendmail (MTA), rather i prefer to use other open source MTA like postfix, qmail or squirelmail to send mail, i have used postfix to do the same thing in past. but anyway, you can use whatever you feel conf with.

by the way, i haven't found any problem using "cin", it just works fine(check my modifications)....
hope this program will help you... good luck......

here, is the program
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <exception>
#include <unistd.h>

using namespace std;

int main()
{
	//Declaring vars to be used
	string subject ("Mail Manager Message");
	string message ("test");
	string email ("xxxx@gmail.com");
	string subscribes ("");
	string unsubscribes ("");
	char grp;
	string group ("");
	FILE *myMail;
	//Make a choice, A or B?
	cout << "A: mudc-com or B: mudc-members?" << endl;
	cin >> grp;
	
	//if A is typed store mudc-com as group. else for B mudc-members as group.
	//if anything else it typed explain that that's not right and quit the program
	if (grp == 'A')
		group = "mudc-com";
	else if (grp == 'B')
		group = "mudc-members";
	else
	{
		cout << "You must enter either A or B" << endl;
		exit(0);
	}

	
	cout << "Enter Subscribes :" ;
	cin>>subscribes;                   //cin.getline(subscribes); - should I be using this somehow?
	cout << "Enter Unsubscribes :";
	cin>>unsubscribes;
	
	// Display what's stored to me so I can verify it's been stored correctly
	cout << "Member Group: "<<group << endl; 
	cout << "Subscribed are: "<<subscribes << endl; 
	cout << "Unsubscribed are: "<<unsubscribes << endl;
	
	
	try {
		if (NULL != (myMail = popen ("/usr/sbin/sendmail -t", "w")))
			{
				fprintf (myMail, "To: %s \n", email.c_str());
				fprintf (myMail, "From: %s \n", subscribes.c_str());
				fprintf (myMail, "Subject: %s\n", subject.c_str());
				fprintf (myMail, "\n");
				fprintf (myMail, "Hello Your job was completed successfully .\n");
				fprintf (myMail, "\n.\n");
				pclose (myMail);
				cout<<"Mail Sent..."<<endl;
			} 
                        else
                        {
                               cout<<"Error sending mail"<<endl;
                        }


	}
	
	// Catch any thrown exceptions...
	catch (exception& e)
	{
		cout << "Exception occured!" << e.what() << "\n"; 
	}
	return 0;
} 
A good solution maxchirag
awesome thank you very much. I didn't use cin however because I needed whole lines inputted.
ie, if I used cin, when shell asked me for subscribes I would type:
blah@email.com; grr@email.com; sidewinder@microsoft.com
but cin seems to stop reading when it encounters a space. so as my output I would have simply:
blah@email.com;

in order to get the full line stored in the var, should getline() or some other method be used.
I read up on getline() but have noticed that it is commonly used to pinpoint input to specific locations in strings/arrays.
ie, cin.getline(object, 128);
as such not sure if it would be applicable in this scenario
also, the email didn't seem to arrive when I did include a valid email in the email var.
I still got the message sent... result however. So the file must have opened successfully.
I'm curious if this may have something to do with \n and possibly even fprinff producing new lines (due to multiple lines perhaps confusing the shell command line interface, but I erased all the /n and the email still didn't arrive
Hello poyntz,

it seems you haven't read out my notes completely , sending mail is not only a C++ job, as i mentioned, you also need to configure the program sending mail (this case sendmail) for you.

what i suggest is, you try to send a mail from command line(manually) and see, the mail arrives or not? if yes, then try to modify your program according to that,

and if simple command line doesn't help you need to configure sendmail for sending mail,

you program is doing nothing but the steps you are performing at shell (using other program to do the task)..... so if the manual version works C++ program must work......

by the way, where you are sending mail? is it your local linux user? or its a some other mail server like gmail or yahoo, or hotmail?

i asked this becuase, if you are sending to other servers, you also need to configure some parameter which will protect your mail against detected as a spam on other server,
Topic archived. No new replies allowed.