Exemplo n.º 1
0
BEmailMessage *
BEmailMessage::ForwardMessage(bool accountFromMail, bool includeAttachments)
{
	BString header = "------ Forwarded Message: ------\n";
	header << "To: " << To() << '\n';
	header << "From: " << From() << '\n';
	if (CC() != NULL) {
		// Can use CC rather than "Cc" since display only.
		header << "CC: " << CC() << '\n';
	}
	header << "Subject: " << Subject() << '\n';
	header << "Date: " << Date() << "\n\n";
	if (_text_body != NULL)
		header << _text_body->Text() << '\n';
	BEmailMessage *message = new BEmailMessage();
	message->SetBodyTextTo(header.String());

	// set the subject
	BString subject = Subject();
	if (subject.IFindFirst("fwd") == B_ERROR
		&& subject.IFindFirst("forward") == B_ERROR
		&& subject.FindFirst("FW") == B_ERROR)
		subject << " (fwd)";
	message->SetSubject(subject.String());

	if (includeAttachments) {
		for (int32 i = 0; i < CountComponents(); i++) {
			BMailComponent *cmpt = GetComponent(i);
			if (cmpt == _text_body || cmpt == NULL)
				continue;

			//---I am ashamed to have the written the code between here and the next comment
			// ... and you still managed to get it wrong ;-)), axeld.
			// we should really move this stuff into copy constructors
			// or something like that

			BMallocIO io;
			cmpt->RenderToRFC822(&io);
			BMailComponent *clone = cmpt->WhatIsThis();
			io.Seek(0, SEEK_SET);
			clone->SetToRFC822(&io, io.BufferLength(), true);
			message->AddComponent(clone);
		}
	}
	if (accountFromMail)
		message->SendViaAccountFrom(this);

	return message;
}
Exemplo n.º 2
0
bool MailingList::DistributeEmail(IncomingMail* ICMail, std::string ogaddrfilepath)
{
	
	//send ICMail to every address in ogaddrfilepath
	std::vector<std::string> recipients;
	BFile recipientlistbfile;
	status_t filestatus=recipientlistbfile.SetTo(ogaddrfilepath.c_str(),B_READ_ONLY);
	if (filestatus!=B_NO_ERROR)
	{
		LogError("ERROR: Could not read temp file from authentication program - the file could not be opened. Does it exist?");
		return false;	
	}
		off_t bytes; //size of file
		if (recipientlistbfile.GetSize(&bytes) == B_NO_ERROR)
		{
		
			char* buff = new char[bytes];
			off_t bytesread=recipientlistbfile.Read(buff,bytes);
			if (bytesread > 0)
			{
				//file read ok
	
				std::string addr="";
	
				for (int x=0; x < bytesread; x++)
				{
					if (buff[x]!='\n')
					{
						addr=addr+buff[x];
					}
					else
					{
						recipients.push_back(addr);
						addr="";	
					}
				}	
				delete buff;
			}
			else
			{
				LogError("ERROR: Could not read temp file from authentication program - the file was empty");
				delete buff;
				return false;	
			}
		}
		else
		{
			LogError("ERROR: Could not read temp file from authentication program -- could not determine file size");
			return false;	
		}
		
		ICMail->AddSubjectPrefix(fListSubjectPrefix); //fListSubjectPrefix will be null str if not defined in conf file
		ICMail->CleanHeaders(); //clean & setup headers ready for sending message out to recipients
		ICMail->AdjustReplyTo(fForceReplyToList); //set reply to to either sender or list IC address
		
		//if List-Xyz header values were set in conf file we need to set them in msg
		if (fListOwner!="")
		{
			ICMail->SetListOwnerHeader(fListOwner);
		}
		if (fListHelp!="")
		{
			ICMail->SetListHelpHeader(fListHelp);
		}
		if (fListArchive!="")
		{
			ICMail->SetListArchiveHeader(fListArchive);
		}
		if (fListSubscribe!="")
		{
			ICMail->SetListSubscribeHeader(fListSubscribe);
		}
		if (fListUnSubscribe!="")
		{
			ICMail->SetListUnSubscribeHeader(fListUnSubscribe);
		}
	//call GetFromField to get email address in case we need to bounce msg 

	std::string ICsendersAddrField=ICMail->GetSendersAddr(); //returns null string if unable to find
	//at present ICsendersAddrField now has address in form user@domain NOT <user@domain> is this in line with RFC spec?
	


	if (ICMail->CheckIfPlainTextCriteriaPassed(fPlainTextOnly)==false)
	{
		//bounce
		if (fPlainTextOnly=='Y')
		{
				//bounce to sender
				LogError("INFO: Incoming email not text/plain and non plain text messages are not allowed. Bounced to "+ICsendersAddrField);
				BMailMessage* ogmail;
				ogmail= new BMailMessage();
				ogmail->AddHeaderField(B_MAIL_TO,ICsendersAddrField.c_str());
				ogmail->AddHeaderField(B_MAIL_FROM,fListOGEnvelopeAddressFromAddress.c_str());
				std::string bouncesubject=std::string("Undelivered mail: Your message to ");
				bouncesubject=bouncesubject+fListName+" was rejected";
				ogmail->AddHeaderField(B_MAIL_SUBJECT,bouncesubject.c_str());
				std::string xmailer=(fApp->GetAppName())+" mailing list server for Haiku";
				ogmail->AddHeaderField("X-Mailer: ",xmailer.c_str());
				ogmail->AddHeaderField("precedence: ","list");
				std::string bouncecontent="Your message to "+fListName+" was rejected because this list only accepts plain text messages. Make sure your email program is not creating HTML or Rich Text emails and that there are no attached files.";
				bouncecontent=bouncecontent+"\n\nThis is an automated reply sent from the "+fApp->GetAppName()+" for Haiku server at "+fListICAddress;
    			ogmail->AddContent(bouncecontent.c_str(),strlen(bouncecontent.c_str()));
				ogmail->Send();
				delete ogmail;
		}
		else
		{
				//fPlainTextOnly must be 'H'
				//bounce to sender
				LogError("INFO: Incoming email not HTML or plain text and non text messages are not allowed. Bounced to "+ICsendersAddrField);
				BMailMessage* ogmail;
				ogmail= new BMailMessage();
				ogmail->AddHeaderField(B_MAIL_TO,ICsendersAddrField.c_str());
				ogmail->AddHeaderField(B_MAIL_FROM,fListOGEnvelopeAddressFromAddress.c_str());
				std::string bouncesubject=std::string("Undelivered mail: Your message to ");
				bouncesubject=bouncesubject+fListName+" was rejected";
				ogmail->AddHeaderField(B_MAIL_SUBJECT,bouncesubject.c_str());
				std::string xmailer=(fApp->GetAppName())+" mailing list server for Haiku";
				ogmail->AddHeaderField("X-Mailer: ",xmailer.c_str());
				ogmail->AddHeaderField("precedence: ","list");
				std::string bouncecontent="Your message to "+fListName+" was rejected because this list only accepts HTML or plain text messages. Make sure that there are no attached files.";
				bouncecontent=bouncecontent+"\n\nThis is an automated reply sent from the "+fApp->GetAppName()+" for Haiku server at "+fListICAddress;
    			ogmail->AddContent(bouncecontent.c_str(),strlen(bouncecontent.c_str()));
				ogmail->Send();
				delete ogmail;
		}
		return true;
	}

	
	if (ICMail->GetICFileSize() > fMaxContentBytes)
	{
		//msg too big bounce to sender
		LogError("INFO: Incoming email too big. Bounced to "+ICsendersAddrField);
		BMailMessage* ogmail;
		ogmail= new BMailMessage();
		ogmail->AddHeaderField(B_MAIL_TO,ICsendersAddrField.c_str());
		ogmail->AddHeaderField(B_MAIL_FROM,fListOGEnvelopeAddressFromAddress.c_str());
		std::string bouncesubject=std::string("Undelivered mail: Your message to ");
		bouncesubject=bouncesubject+fListName+" was rejected";
		ogmail->AddHeaderField(B_MAIL_SUBJECT,bouncesubject.c_str());
		std::string xmailer=(fApp->GetAppName())+" mailing list server for Haiku";
		ogmail->AddHeaderField("X-Mailer: ",xmailer.c_str());
		ogmail->AddHeaderField("precedence: ","list");
		stringstream converter;
		converter << fMaxContentBytes << " bytes, your message was " << ICMail->GetICFileSize() << " bytes";
		std::string toobigcontent="Your message to "+fListName+" is too big and was rejected. Maximum allowable size for this list is "+converter.str();
		toobigcontent=toobigcontent+"\n\nThis is an automated reply sent from the "+fApp->GetAppName()+" for Haiku server at "+fListICAddress;
    	ogmail->AddContent(toobigcontent.c_str(),strlen(toobigcontent.c_str()));
		ogmail->Send();
		delete ogmail;
		return true;
	}



	//setup a temp file to store the modified og msg
	std::stringstream epochsecs;
	epochsecs << real_time_clock(); //secs now since unix epoch
	int filenamecounterInt=0; //will be incremented until we get a unique filename string
	bool nonuniquefilename=true;
	BEntry tempFileBEntry;
	std::string tempFilePath;
	BFile* tempFileBFile = new BFile();
	do
	{
		filenamecounterInt++;
		std::stringstream filenamecounter;
		filenamecounter << filenamecounterInt;
		tempFilePath=fApp->GetTempDirPath()+fListICAddress+"--"+epochsecs.str()+filenamecounter.str();
		//test if tempFilePath already exists
		tempFileBEntry.SetTo(tempFilePath.c_str());
		status_t tempFileResult=tempFileBFile->SetTo(&tempFileBEntry,B_READ_WRITE|B_FAIL_IF_EXISTS|B_CREATE_FILE); //fails if already exists
		if (tempFileResult==B_FILE_EXISTS)
		{
			nonuniquefilename=true;	
		}
		else if (tempFileResult==B_NO_ERROR)
		{
			nonuniquefilename=false;
			
		}
		else
		{
			//error
			LogError("ERROR: Could not create temp file to store outgoing email");
			return false;
		}
		
	}while(nonuniquefilename);

	//Write modified msg into temp file

	ICMail->WriteToFile(tempFileBFile);



	//store senders addr so we can log it later
	std::string sender="";
	//Send out modified msg in temp file to all recipients
	for (int x=0; x< recipients.size(); x++)
	{
		std::string recipient=recipients[x];
		
		BEmailMessage* ogmail;
		ogmail= new BEmailMessage(tempFileBFile);
    	ogmail->SetTo(recipient.c_str());
    	sender=std::string(ogmail->From());
    	//1st version of send indicates whether to change the From: field to the specified account (requires modified mailkit)
		ogmail->SendViaAccountWithFromPreset(fListOGEnvelopeAddressFromAddress.c_str());
		//ogmail->SendViaAccount(fListOGEnvelopeAddressFromAddress.c_str());
		ogmail->Send(true);
		delete ogmail;
		
	}
	tempFileBFile->Unset(); //close file
	delete tempFileBFile; //delete obj
	//archive msg if needed
	bool archived=false;
	if (fArchivePath!="")
	{
			
			BDirectory dir;
			if ( dir.SetTo(fArchivePath.c_str()) !=B_OK )
			{
				LogError("ERROR: Could not archive message. Check archive folder exists and is writable");
			}
			else
			{
				if ( tempFileBEntry.MoveTo(&dir) !=B_NO_ERROR)
				{
					LogError("ERROR: Could not archive message. Check archive folder exists and is writable");
				}
				else
				{
					archived=true;	
				}
			}
			
	}
	if (archived==false)
	{
		//if archived  then the file was moved so we dont need to delete the original
		tempFileBEntry.Remove();//remove file from filesystem	
	}
	
	stringstream numRecipients;
	numRecipients << recipients.size();
	
	if ( (fLogSuccesses) && (recipients.size()>0)  )
	{
		//if we recipients.size() was 0 sender var is null str as its set in the distribution loop
		LogError("INFO: Successfully distributed an email to "+numRecipients.str()+" recipients from "+sender);
	}
	return true;
}
Exemplo n.º 3
0
BEmailMessage *
BEmailMessage::ReplyMessage(mail_reply_to_mode replyTo, bool accountFromMail,
	const char *quoteStyle)
{
	BEmailMessage *reply = new BEmailMessage;

	// Set ReplyTo:

	if (replyTo == B_MAIL_REPLY_TO_ALL) {
		reply->SetTo(From());

		BList list;
		get_address_list(list, CC(), extract_address);
		get_address_list(list, To(), extract_address);

		// Filter out the sender
		BMailAccounts accounts;
		BMailAccountSettings* account = accounts.AccountByID(Account());
		BString sender;
		if (account)
			sender = account->ReturnAddress();
		extract_address(sender);

		BString cc;

		for (int32 i = list.CountItems(); i-- > 0;) {
			char *address = (char *)list.RemoveItem((int32)0);

			// add everything which is not the sender and not already in the list
			if (sender.ICompare(address) && cc.FindFirst(address) < 0) {
				if (cc.Length() > 0)
					cc << ", ";

				cc << address;
			}

			free(address);
		}

		if (cc.Length() > 0)
			reply->SetCC(cc.String());
	} else if (replyTo == B_MAIL_REPLY_TO_SENDER || ReplyTo() == NULL)
		reply->SetTo(From());
	else
		reply->SetTo(ReplyTo());

	// Set special "In-Reply-To:" header (used for threading)
	const char *messageID = _body ? _body->HeaderField("Message-Id") : NULL;
	if (messageID != NULL)
		reply->SetHeaderField("In-Reply-To", messageID);

	// quote body text
	reply->SetBodyTextTo(BodyText());
	if (quoteStyle)
		reply->Body()->Quote(quoteStyle);

	// Set the subject (and add a "Re:" if needed)
	BString string = Subject();
	if (string.ICompare("re:", 3) != 0)
		string.Prepend("Re: ");
	reply->SetSubject(string.String());

	// set the matching outbound chain
	if (accountFromMail)
		reply->SendViaAccountFrom(this);

	return reply;
}