Click here to Skip to main content
15,896,118 members
Articles / Web Development / IIS

Reading a text file in ASP.

Rate me:
Please Sign up or sign in to vote.
4.96/5 (15 votes)
18 Mar 2009CPOL 764.6K   4.1K   54  
How to read a text file on a server using VBScript in ASP
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 3 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// Linking this library statically or dynamically with other modules is making
// a combined work based on this library.  Thus, the terms and conditions of
// the GNU General Public License cover the whole combination.
//

#include <iostream>
#include <sstream>
#include <vector>
#include <map>

#include "vmime/vmime.hpp"
#include "vmime/platforms/posix/posixHandler.hpp"


// Global session object
static vmime::ref <vmime::net::session> g_session
	= vmime::create <vmime::net::session>();


#if VMIME_HAVE_SASL_SUPPORT

// SASL authentication handler
class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator
{
	const std::vector <vmime::ref <vmime::security::sasl::SASLMechanism> > getAcceptableMechanisms
		(const std::vector <vmime::ref <vmime::security::sasl::SASLMechanism> >& available,
		 vmime::ref <vmime::security::sasl::SASLMechanism> suggested) const
	{
		std::cout << std::endl << "Available SASL mechanisms:" << std::endl;

		for (unsigned int i = 0 ; i < available.size() ; ++i)
		{
			std::cout << "  " << available[i]->getName();

			if (suggested && available[i]->getName() == suggested->getName())
				std::cout << "(suggested)";
		}

		std::cout << std::endl << std::endl;

		return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested);
	}

	void setSASLMechanism(vmime::ref <vmime::security::sasl::SASLMechanism> mech)
	{
		std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl;

		defaultSASLAuthenticator::setSASLMechanism(mech);
	}

	const vmime::string getUsername() const
	{
		if (m_username.empty())
			m_username = getUserInput("Username");

		return m_username;
	}

	const vmime::string getPassword() const
	{
		if (m_password.empty())
			m_password = getUserInput("Password");

		return m_password;
	}

	static const vmime::string getUserInput(const std::string& prompt)
	{
		std::cout << prompt << ": ";
		std::cout.flush();

		vmime::string res;
		std::getline(std::cin, res);

		return res;
	}

private:

	mutable vmime::string m_username;
	mutable vmime::string m_password;
};

#else // !VMIME_HAVE_SASL_SUPPORT

// Simple authentication handler
class interactiveAuthenticator : public vmime::security::defaultAuthenticator
{
	const vmime::string getUsername() const
	{
		if (m_username.empty())
			m_username = getUserInput("Username");

		return m_username;
	}

	const vmime::string getPassword() const
	{
		if (m_password.empty())
			m_password = getUserInput("Password");

		return m_password;
	}

	static const vmime::string getUserInput(const std::string& prompt)
	{
		std::cout << prompt << ": ";
		std::cout.flush();

		vmime::string res;
		std::getline(std::cin, res);

		return res;
	}

private:

	mutable vmime::string m_username;
	mutable vmime::string m_password;
};

#endif // VMIME_HAVE_SASL_SUPPORT


#if VMIME_HAVE_TLS_SUPPORT

// Certificate verifier (TLS/SSL)
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier
{
public:

	void verify(vmime::ref <vmime::security::cert::certificateChain> chain, const vmime::string& hostname)
	{
		try
		{
			setX509TrustedCerts(m_trustedCerts);

			defaultCertificateVerifier::verify(chain, hostname);
		}
		catch (vmime::exceptions::certificate_verification_exception&)
		{
			// Obtain subject's certificate
			vmime::ref <vmime::security::cert::certificate> cert = chain->getAt(0);

			std::cout << std::endl;
			std::cout << "Server sent a '" << cert->getType() << "'" << " certificate." << std::endl;
			std::cout << "Do you want to accept this certificate? (Y/n) ";
			std::cout.flush();

			std::string answer;
			std::getline(std::cin, answer);

			if (answer.length() != 0 &&
			    (answer[0] == 'Y' || answer[0] == 'y'))
			{
				// Accept it, and remember user's choice for later
				if (cert->getType() == "X.509")
				{
					m_trustedCerts.push_back(cert.dynamicCast
						<vmime::security::cert::X509Certificate>());

					setX509TrustedCerts(m_trustedCerts);
					defaultCertificateVerifier::verify(chain, hostname);
				}

				return;
			}

			throw vmime::exceptions::certificate_verification_exception
				("User did not accept the certificate.");
		}
	}

private:

	static std::vector <vmime::ref <vmime::security::cert::X509Certificate> > m_trustedCerts;
};


std::vector <vmime::ref <vmime::security::cert::X509Certificate> >
	interactiveCertificateVerifier::m_trustedCerts;

#endif // VMIME_HAVE_TLS_SUPPORT


/** Returns the messaging protocols supported by VMime.
  *
  * @param type service type (vmime::net::service::TYPE_STORE or
  * vmime::net::service::TYPE_TRANSPORT)
  */
static const std::string findAvailableProtocols(const vmime::net::service::Type type)
{
	vmime::net::serviceFactory* sf = vmime::net::serviceFactory::getInstance();

	std::ostringstream res;
	int count = 0;

	for (int i = 0 ; i < sf->getServiceCount() ; ++i)
	{
		const vmime::net::serviceFactory::registeredService& serv = *sf->getServiceAt(i);

		if (serv.getType() == type)
		{
			if (count != 0)
				res << ", ";

			res << serv.getName();
			++count;
		}
	}

	return res.str();
}


// Exception helper
static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
{
	os << "* vmime::exceptions::" << e.name() << std::endl;
	os << "    what = " << e.what() << std::endl;

	// More information for special exceptions
	if (dynamic_cast <const vmime::exceptions::command_error*>(&e))
	{
		const vmime::exceptions::command_error& cee =
			dynamic_cast <const vmime::exceptions::command_error&>(e);

		os << "    command = " << cee.command() << std::endl;
		os << "    response = " << cee.response() << std::endl;
	}

	if (dynamic_cast <const vmime::exceptions::invalid_response*>(&e))
	{
		const vmime::exceptions::invalid_response& ir =
			dynamic_cast <const vmime::exceptions::invalid_response&>(e);

		os << "    response = " << ir.response() << std::endl;
	}

	if (dynamic_cast <const vmime::exceptions::connection_greeting_error*>(&e))
	{
		const vmime::exceptions::connection_greeting_error& cgee =
			dynamic_cast <const vmime::exceptions::connection_greeting_error&>(e);

		os << "    response = " << cgee.response() << std::endl;
	}

	if (dynamic_cast <const vmime::exceptions::authentication_error*>(&e))
	{
		const vmime::exceptions::authentication_error& aee =
			dynamic_cast <const vmime::exceptions::authentication_error&>(e);

		os << "    response = " << aee.response() << std::endl;
	}

	if (dynamic_cast <const vmime::exceptions::filesystem_exception*>(&e))
	{
		const vmime::exceptions::filesystem_exception& fse =
			dynamic_cast <const vmime::exceptions::filesystem_exception&>(e);

		os << "    path = " << vmime::platform::getHandler()->
			getFileSystemFactory()->pathToString(fse.path()) << std::endl;
	}

	if (e.other() != NULL)
		os << *e.other();

	return os;
}


/** Print the MIME structure of a message on the standard output.
  *
  * @param s structure object
  * @param level current depth
  */
static void printStructure(vmime::ref <const vmime::net::messageStructure> s, const int level = 0)
{
	for (int i = 0 ; i < s->getPartCount() ; ++i)
	{
		vmime::ref <const vmime::net::messagePart> part = s->getPartAt(i);

		for (int j = 0 ; j < level * 2 ; ++j)
			std::cout << " ";

		std::cout << (part->getNumber() + 1) << ". "
				<< part->getType().generate()
				<< " [" << part->getSize() << " byte(s)]"
				<< std::endl;

		printStructure(part->getStructure(), level + 1);
	}
}


static const vmime::string getFolderPathString(vmime::ref <vmime::net::folder> f)
{
	const vmime::string n = f->getName().getBuffer();

	if (n.empty()) // root folder
	{
		return "/";
	}
	else
	{
		vmime::ref <vmime::net::folder> p = f->getParent();
		return getFolderPathString(p) + n + "/";
	}
}


/** Print folders and sub-folders on the standard output.
  *
  * @param folder current folder
  */
static void printFolders(vmime::ref <vmime::net::folder> folder, const int level = 0)
{
	for (int j = 0 ; j < level * 2 ; ++j)
		std::cout << " ";

	std::cout << getFolderPathString(folder) << std::endl;

	std::vector <vmime::ref <vmime::net::folder> > subFolders = folder->getFolders(false);

	for (unsigned int i = 0 ; i < subFolders.size() ; ++i)
		printFolders(subFolders[i], level + 1);
}


/** Print a menu on the standard output.
  *
  * @param choices menu choices
  */
static unsigned int printMenu(const std::vector <std::string>& choices)
{
	std::cout << std::endl;

	for (unsigned int i = 0 ; i < choices.size() ; ++i)
		std::cout << "   " << (i + 1) << ". " << choices[i] << std::endl;

	std::cout << std::endl;
	std::cout << "   Your choice? [1-" << choices.size() << "] ";
	std::cout.flush();

	std::string line;
	std::getline(std::cin, line);

	std::istringstream iss(line);

	unsigned int choice = 0;
	iss >> choice;

	std::cout << std::endl;

	if (choice < 1 || choice > choices.size())
		return 0;
	else
		return choice;
}


/** Send a message interactively.
  */
static void sendMessage()
{
	try
	{
		// Request user to enter an URL
		std::cout << "Enter an URL to connect to transport service." << std::endl;
		std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_TRANSPORT) << std::endl;
		std::cout << "(eg. smtp://myserver.com, sendmail://localhost)" << std::endl;
		std::cout << "> ";
		std::cout.flush();

		vmime::string urlString;
		std::getline(std::cin, urlString);

		vmime::utility::url url(urlString);

		vmime::ref <vmime::net::transport> tr =
			g_session->getTransport(url, vmime::create <interactiveAuthenticator>());

#if VMIME_HAVE_TLS_SUPPORT

		// Enable TLS support if available
		tr->setProperty("connection.tls", true);

		// Set the object responsible for verifying certificates, in the
		// case a secured connection is used (TLS/SSL)
		tr->setCertificateVerifier
			(vmime::create <interactiveCertificateVerifier>());

#endif // VMIME_HAVE_TLS_SUPPORT

		// You can also set some properties (see example7 to know the properties
		// available for each service). For example, for SMTP:
//		tr->setProperty("options.need-authentication", true);

		// Information about the mail
		std::cout << "Enter email of the expeditor (eg. me@somewhere.com): ";
		std::cout.flush();

		vmime::string fromString;
		std::getline(std::cin, fromString);

		vmime::mailbox from(fromString);
		vmime::mailboxList to;

		for (bool cont = true ; cont ; )
		{
			std::cout << "Enter email of the recipient (empty to stop): ";
			std::cout.flush();

			vmime::string toString;
			std::getline(std::cin, toString);

			cont = (toString.size() != 0);

			if (cont)
				to.appendMailbox(vmime::create <vmime::mailbox>(toString));
		}

		std::cout << "Enter message data, including headers (end with '.' on a single line):" << std::endl;

		std::ostringstream data;

		for (bool cont = true ; cont ; )
		{
			std::string line;
			std::getline(std::cin, line);

			if (line == ".")
				cont = false;
			else
				data << line << "\r\n";
		}

		// Connect to server
		tr->connect();

		// Send the message
		vmime::string msgData = data.str();
		vmime::utility::inputStreamStringAdapter vis(msgData);

		tr->send(from, to, vis, msgData.length());

		// Note: you could also write this:
		//     vmime::message msg;
		//     ...
		//     tr->send(&msg);

		tr->disconnect();
	}
	catch (vmime::exception& e)
	{
		std::cerr << std::endl;
		std::cerr << e << std::endl;
		throw;
	}
	catch (std::exception& e)
	{
		std::cerr << std::endl;
		std::cerr << "std::exception: " << e.what() << std::endl;
		throw;
	}
}


/** Connect to a message store interactively.
  */
static void connectStore()
{
	try
	{
		// Request user to enter an URL
		std::cout << "Enter an URL to connect to store service." << std::endl;
		std::cout << "Available protocols: " << findAvailableProtocols(vmime::net::service::TYPE_STORE) << std::endl;
		std::cout << "(eg. pop3://user:pass@myserver.com, imap://myserver.com:123)" << std::endl;
		std::cout << "> ";
		std::cout.flush();

		vmime::string urlString;
		std::getline(std::cin, urlString);

		vmime::utility::url url(urlString);

		// If no authenticator is given in argument to getStore(), a default one
		// is used. Its behaviour is to get the user credentials from the
		// session properties "auth.username" and "auth.password".
		vmime::ref <vmime::net::store> st;

		if (url.getUsername().empty() || url.getPassword().empty())
			st = g_session->getStore(url, vmime::create <interactiveAuthenticator>());
		else
			st = g_session->getStore(url);

#if VMIME_HAVE_TLS_SUPPORT

		// Enable TLS support if available
		st->setProperty("connection.tls", true);

		// Set the object responsible for verifying certificates, in the
		// case a secured connection is used (TLS/SSL)
		st->setCertificateVerifier
			(vmime::create <interactiveCertificateVerifier>());

#endif // VMIME_HAVE_TLS_SUPPORT

		// Connect to the mail store
		st->connect();

		// Display some information about the connection
		vmime::ref <vmime::net::connectionInfos> ci = st->getConnectionInfos();

		std::cout << std::endl;
		std::cout << "Connected to '" << ci->getHost() << "' (port " << ci->getPort() << ")" << std::endl;
		std::cout << "Connection is " << (st->isSecuredConnection() ? "" : "NOT ") << "secured." << std::endl;

		// Open the default folder in this store
		vmime::ref <vmime::net::folder> f = st->getDefaultFolder();
//		vmime::ref <vmime::net::folder> f = st->getFolder(vmime::utility::path("a"));

		f->open(vmime::net::folder::MODE_READ_WRITE);

		int count = f->getMessageCount();

		std::cout << std::endl;
		std::cout << count << " message(s) in your inbox" << std::endl;

		for (bool cont = true ; cont ; )
		{
			typedef std::map <int, vmime::ref <vmime::net::message> > MessageList;
			MessageList msgList;

			try
			{
				std::vector <std::string> choices;

				choices.push_back("Show message flags");
				choices.push_back("Show message structure");
				choices.push_back("Show message header");
				choices.push_back("Show message envelope");
				choices.push_back("Extract whole message");
				choices.push_back("Status");
				choices.push_back("List folders");
				choices.push_back("Change folder");
				choices.push_back("Return to main menu");

				const int choice = printMenu(choices);

				// Request message number
				vmime::ref <vmime::net::message> msg;

				if (choice != 6 && choice != 7 && choice != 8)
				{
					std::cout << "Enter message number: ";
					std::cout.flush();

					std::string line;
					std::getline(std::cin, line);

					std::istringstream iss(line);

					int num = 0;
					iss >> num;

					if (num < 1 || num > count)
					{
						std::cerr << "Invalid message number." << std::endl;
						continue;
					}

					MessageList::iterator it = msgList.find(num);

					if (it != msgList.end())
					{
						msg = (*it).second;
					}
					else
					{
						msg = f->getMessage(num);
						msgList.insert(MessageList::value_type(num, msg));
					}

					std::cout << std::endl;
				}

				switch (choice)
				{
				// Show message flags
				case 1:

					f->fetchMessage(msg, vmime::net::folder::FETCH_FLAGS);

					if (msg->getFlags() & vmime::net::message::FLAG_SEEN)
						std::cout << "FLAG_SEEN" << std::endl;
					if (msg->getFlags() & vmime::net::message::FLAG_RECENT)
						std::cout << "FLAG_RECENT" << std::endl;
					if (msg->getFlags() & vmime::net::message::FLAG_REPLIED)
						std::cout << "FLAG_REPLIED" << std::endl;
					if (msg->getFlags() & vmime::net::message::FLAG_DELETED)
						std::cout << "FLAG_DELETED" << std::endl;
					if (msg->getFlags() & vmime::net::message::FLAG_MARKED)
						std::cout << "FLAG_MARKED" << std::endl;
					if (msg->getFlags() & vmime::net::message::FLAG_PASSED)
						std::cout << "FLAG_PASSED" << std::endl;

					break;

				// Show message structure
				case 2:

					f->fetchMessage(msg, vmime::net::folder::FETCH_STRUCTURE);
					printStructure(msg->getStructure());
					break;

				// Show message header
				case 3:

					f->fetchMessage(msg, vmime::net::folder::FETCH_FULL_HEADER);
					std::cout << msg->getHeader()->generate() << std::endl;
					break;

				// Show message envelope
				case 4:

					f->fetchMessage(msg, vmime::net::folder::FETCH_ENVELOPE);

#define ENV_HELPER(x) \
	try { std::cout << msg->getHeader()->x()->generate() << std::endl; } \
	catch (vmime::exception) { /* In case the header field does not exist. */ }

					ENV_HELPER(From)
					ENV_HELPER(To)
					ENV_HELPER(Date)
					ENV_HELPER(Subject)

#undef ENV_HELPER

					break;

				// Extract whole message
				case 5:
				{
					vmime::utility::outputStreamAdapter out(std::cout);
					msg->extract(out);

					break;
				}
				// Status
				case 6:
				{
					int count, unseen;
					f->status(count, unseen);

					std::cout << "Status: count=" << count << ", unseen=" << unseen << std::endl;
					break;
				}
				// List folders
				case 7:
				{
					vmime::ref <vmime::net::folder>
						root = st->getRootFolder();

					printFolders(root);
					break;
				}
				// Change folder
				case 8:
				{
					std::cout << "Enter folder path (eg. /root/subfolder):" << std::endl;
					std::cout.flush();

					std::string path;
					std::getline(std::cin, path);

					vmime::ref <vmime::net::folder> newFolder = st->getRootFolder();

					for (std::string::size_type s = 0, p = 0 ; ; s = p + 1)
					{
						p = path.find_first_of('/', s);

						const std::string x = (p == std::string::npos)
							? std::string(path.begin() + s, path.end())
							: std::string(path.begin() + s, path.begin() + p);

						if (!x.empty())
							newFolder = newFolder->getFolder(x);

						if (p == std::string::npos)
							break;
					}

					newFolder->open(vmime::net::folder::MODE_READ_WRITE);

					count = newFolder->getMessageCount();

					std::cout << std::endl;
					std::cout << count << " message(s) in this folder" << std::endl;

					f->close(true);  // 'true' to expunge deleted messages
					f = newFolder;

					break;
				}
				// Main menu
				case 9:

					f->close(true);  // 'true' to expunge deleted messages
					cont = false;
					break;
				}

/*
		// Append message
		std::istringstream iss(
			"From: me@localhost\r\n"
			"To: you@localhost\r\n"
			"Subject: Message Text\r\n"
			"\r\n"
			"This is a test message...\r\n"
			"Bye bye!\r\n"
		);

		f->addMessage(iss, iss.str().size());

		// Folder renaming
		{
			vmime::ref <vmime::net::folder> f = st->getFolder(vmime::net::folder::path("c"));
			f->rename(vmime::net::folder::path("c2"));

			vmime::ref <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("c2"));
			g->rename(vmime::net::folder::path("c"));
		}

		// Message copy: copy all messages from 'f' to 'g'
		{
			vmime::ref <vmime::net::folder> g = st->getFolder(vmime::net::folder::path("TEMP"));

			if (!g->exists())
				g->create(vmime::net::folder::TYPE_CONTAINS_MESSAGES);

			f->copyMessages(g->getFullPath());
		}
*/
			}
			catch (vmime::exception& e)
			{
				std::cerr << std::endl;
				std::cerr << e << std::endl;
			}
			catch (std::exception& e)
			{
				std::cerr << std::endl;
				std::cerr << "std::exception: " << e.what() << std::endl;
			}
		}
	}
	catch (vmime::exception& e)
	{
		std::cerr << std::endl;
		std::cerr << e << std::endl;
		throw;
	}
	catch (std::exception& e)
	{
		std::cerr << std::endl;
		std::cerr << "std::exception: " << e.what() << std::endl;
		throw;
	}
}


/* Show the main menu.
 *
 * @return true to quit the program, false to continue
 */
static bool menu()
{
	std::vector <std::string> items;

	items.push_back("Connect to a message store");
	items.push_back("Send a message");
	items.push_back("Quit");

	switch (printMenu(items))
	{
	// Connect to store
	case 1:

		connectStore();
		return false;

	// Send a message
	case 2:

		sendMessage();
		return false;

	// Quit
	case 3:

		return true;

	// Other choice
	default:

		return false;
	}
}


int main()
{
	// VMime initialization
	vmime::platform::setHandler<vmime::platforms::posix::posixHandler>();

	for (bool quit = false ; !quit ; )
	{
		// Loop on main menu
		quit = menu();
	}

	return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Founder CodeProject
Canada Canada
Chris Maunder is the co-founder of CodeProject and ContentLab.com, and has been a prominent figure in the software development community for nearly 30 years. Hailing from Australia, Chris has a background in Mathematics, Astrophysics, Environmental Engineering and Defence Research. His programming endeavours span everything from FORTRAN on Super Computers, C++/MFC on Windows, through to to high-load .NET web applications and Python AI applications on everything from macOS to a Raspberry Pi. Chris is a full-stack developer who is as comfortable with SQL as he is with CSS.

In the late 1990s, he and his business partner David Cunningham recognized the need for a platform that would facilitate knowledge-sharing among developers, leading to the establishment of CodeProject.com in 1999. Chris's expertise in programming and his passion for fostering a collaborative environment have played a pivotal role in the success of CodeProject.com. Over the years, the website has grown into a vibrant community where programmers worldwide can connect, exchange ideas, and find solutions to coding challenges. Chris is a prolific contributor to the developer community through his articles and tutorials, and his latest passion project, CodeProject.AI.

In addition to his work with CodeProject.com, Chris co-founded ContentLab and DeveloperMedia, two projects focussed on helping companies make their Software Projects a success. Chris's roles included Product Development, Content Creation, Client Satisfaction and Systems Automation.

Comments and Discussions