MailSend - The Story of a Humble Command-Line Email Utility
I used to sell a command-line email utility that I had written for 32-bit implementations of Microsoft Windows. The utility was named MailSend ( not to be confused with the three or four other command-line mailers which share the name. ) The domain name that I used to host MailSend and other utilities, mailsend-online.com has come up for renewal. After 23 or so years of having that domain, I think it’s time to retire it.
MailSend was the first of my independent application to achieve widespread use. Although it’s no longer something that I sell, I wanted to document the experience of developing and selling MailSend and other applications from my point of view for historical purposes.
This single document was constructed from the ten individual posts that I had placed at the former mailsend-online.com site.
MailSend - The Early Days
I was quite energetic about writing and selling my own software in the mid-90’s. Perhaps not as energetic as people who made lots of money, but I put a fair amount of time into the study of people who made money selling products on their own. In 1997, I happened to be writing a review of the Thompson Automation AWK compiler for an article I had pitched to Dr. Dobbs Journal called Examining the TAWK Compiler.
For the article, I had written a small client for the Internet finger protocol to demonstrate the compiler’s versatility. As I was going over the code, I had wondered what it would take to flesh out the finger client a little more to make an SMTP e-mail client.
My first attempt was fruitful. I had a command-line emailer working that would simply send text messages via SMTP mail without a lot of frilly features. I did not initially support attachments or other niceties. I decided to use my new creation, MailSend, as a test to learn more about independent software sales.
I found out how to format the supplementary readme files and metadata files whose origins could be traced back to the download sections of electronic Bulletin-Board Systems. I wrote a license agreement and a liberal support policy. I offered free upgrades for life. My thinking was that I was going to be constantly evolving the product, so if bugs or defects arose, I would simply ask the client to obtain the free upgrade to see if they could recreate the problem with the newest version. I was concerned about being able to support multiple simultaneous versions.
Another concern I had was that I had written the code in a pretty obscure compiler: TAWK. I had reasoned that the entire command-line compiler and the source code to MailSend fit neatly on one 1.44M floppy disk … so I could carry it around and could recompile it on just about any machine. After discussing things with the folks on alt.comp.shareware.programmer, I found that many of them took non-traditional approaches to writing their software as well. Some wrote in PowerBASIC, many wrote in Delphi, some in varieties of C/C++. I began to realize that the lone wolf developer needed to leverage whatever they were most comfortable with, as long as the tool itself did not become obsolete.
I priced the software at $10 ( another mistake ) and made a few announcements here and there on various newgroups and forums.
The Early Sales
I was very happy when the first checks made their way to my mailbox. I was seeing a nice little stream of money for this product, but it wasn’t anywhere near what the professionals on a.c.s.p. were making with their software.
After accepting only checks via mail for quite some time, I received an e-mail from a corporate prospect who asked me if I could accept payment via credit-card. I couldn’t at the time, but I asked him to let me see if I could find a card processor. I then signed up for RegSoft ( which later became a Digital River company. ) Although I seemed to have a gift for making mistakes along the way, signing up with RegSoft was the best decision I had made regarding MailSend. In 24 hours after signing up, they processed two orders for MailSend. Neither of these was from the gentleman who had asked if he could pay with a credit-card.
The registrations were becoming much more frequent than the checks-in-the-mail had been. My mentors in a.c.s.p. attributed this to impulse buying; It’s easier to procrastinate on a purchase if it takes work ( such as writing out a check, addressing an envelope, …etc. ) If one can simply fill out a web page and receive a product electronically in a short time, chances are greater that the sale will commence.
Sometime around these years, I also began participating in what had been known as the Euro-Share mail-list. Lots of good conversations went on there.
I should note that I also added a limiting factor to the trial version of MailSend at this time. One could only send about ten emails using the trial version. After that, they would have to reboot their machine so that they could send another ten.
I would still refer to the monthly income I was making as hobby-level money, but it was GOOD hobby-level money. I began to grow my stable of products with some other utilities. By the time the year 2000 had rolled around, I felt like a true independent software developer, although I didn’t make nearly enough to quit my day-job.
I was off and running. I was an independent software author with a small but growing list of products. MailSend was the first and it was the most successful in terms of sales and popularity.
HangUp, TSched, WallShow, and WallMake
My MailSend customers would often ask me about programs that could supplement MailSend. Some asked for schedulers, some asked about controlling dialup networking back when many ISP’s charged by the minute for time on the Internet. I sat down one morning and wrote two utilities: HangUp and TSched.
HangUp
HangUp was just a program that would hang up the first dialup connection using the RAS ( Remote Access Services ) API. The program was very simple. Here’s a look at the version of the source for the unprotected registered version:
#include <stdio.h>
#include <windows.h>
#include <ras.h>
#pragma comment(lib, "rasapi32.lib")
main(int argc,char **argv)
{
RASCONN r;
DWORD siz,num;
printf("Hang Up! V 2.0\nCopyright (c) 2009 by Jim Lawless\n");
printf("(See MIT/X11 license in the source code)\n");
r.dwSize=siz=sizeof(RASCONN);
RasEnumConnections(&r,&siz,&num);
if( num == 0 ) {
printf("No connections found! Terminating.\n");
exit(1);
}
RasHangUp(r.hrasconn);
Sleep(3000);
printf("Done.\n");
exit(0);
}
That’s it! It’s just what some of my MailSend customers wanted. In fact, one customer licensed a copy for quite a number of machines, resulting in a good sized license fee.
TSched
TSched was a tiny scheduler. You ran it specifying the time that you wanted a command to run as one of the first arguments, then you specified the command and all of its parameters as the remainder of the arguments. TSched would wait until the specified time to execute the command.
This also picked up a large bulk sale for a company that did certification training. They automated their certification exams using TSched so that they would all launch at the same time. Their representative called me up already having a decent license fee in mind. I didn’t haggle. It was a good deal.
WallShow and WallMake
I was enjoying a nice hobbyist level of income from my command-line tools, but I had wondered if I could also break into the consumer market. I wrote a program using Visual C++ that placed a selected set of graphics images into the Windows wallpaper / background. I bought a DLL that permitted me to convert JPG, GIF, and other file formats to Windows bitmap image files.
I built the installer myself. I was told by one reviewer that it was not good. I tend to agree with him.
I also built the protection scheme myself. I watermarked every image with text such as “unregistered evaluation copy” and every other image or so was a reminder to register. I read more than one review that had said that I overprotected the software. I agree there, too.
It only sold a couple of copies. It was cracked very quickly. The cracker removed the watermark text. I followed up with a release that rendered the crack inert, but I was kind of happy that the program had been popular enough that someone felt the need to try to take it without paying for it.
WallMake was a command-line counterpart to WallShow. You just specified the path and filename of an image and it would set your background / wallpaper to that image. I sold this at first, but I soon started giving this away as freeware.
These attempts to provide a form of entertainment software really fell flat. But that wouldn’t stop me. More programs were in the works!
MailGrab - A Command-Line POP3 Client
A number of people were asking if I had a counterpart for MailSend that would allow them to read mail via a command-line. I had thought about such a utility, but the practice of reading email differs from that of sending mail. It’s easy to envision text and or files that are produced by some sort of process that can be then send out via SMTP, but what would the automation of processing inbound email look like? Was it something that I could even capture in a command-line tool?
The POP3 protocol itself is pretty simple. The complicated parts are the layered types of encoding that can appear in the mail headers and payload. Emailers were beginning to send email in two forms: plain old text and HTML. The headers that appeared before each in the POP3 data stream enabled mail clients to read and display either, presumably depending on some choice that the end user has made. Other data types were also possible depending on MIME ( Minimal Internet Mail Extensions ) encoding. MIME also allowed for base64-encoded attachments. There were other sigils that could appear in text that were mean to begin escape sequences for embedded control codes in the body of the emails.
I built a simple POP3 client called MailGrab. I also built it in TAWK. Why mess with a good thing? I used my own inbound emails as test candidates for the tool and I learned a lot. One of the things I learned was that some email clients (or perhaps the servers) were broken. They produced emails which did not have fully encoded blocks. So, my little emailer handled a number of these edge cases where the incoming email was somewhat mangled.
MailGrab had only a few options. It could retrieve a full POP3 payload or it could retrieve those sections that did not appear to be attachments. It could delete the emails once downloaded, or it could leave them fully intact. With a simple set of functions such as these, I made MailGrab available via the shareware method, again. It did well enough. There were fewer competitors to MailGrab back then.
It won a ZDNet “Editor’s Pick” award (4 stars). I proudly displayed the award graphic on this very site:
People were using combinations of MailSend and MailGrab to perform all sorts of mail automation tasks. One person wrote an email client in Microsoft’s QBASIC interpreter that invoked MailSend and MailGrab to manage the actual email send / receive functions. This was a unique trait about 32-bit command-line software: it could be invoked from a 16-bit program. My tools were used by a number of people who were using some older 16-bit tools such as the Clipper xBase compiler. One of my clients purchased a reseller’s license to each tool because their main product was written in a specialty database language (not unlike Clipper) and they needed to offer their clients email functionality from within the app.
While I really enjoyed interacting with the folks who were using the software, it became too difficult for me to support. I don’t think I had really built it correctly and each time a new upgrade of a given mail server came out, I found myself trying to figure out why MailGrab wasn’t parsing the emails correctly. It was usually my fault. After one particularly grueling fix to the software, I made the choice to quit selling MailSend. I kept supporting my existing customers for a while, but I was no longer permitting active sales.
Although I toy with the idea of writing more POP3 (and or IMAP) mail automation tools, I haven’t implemented anything else in that genre of software, yet.
Envy, BPL, and Run & Hide
I had been spending some time in the Usenet groups comp.os.msdos.batch and comp.os.msdos.batch.nt. Those were fun groups. Participants in those groups were usually talking about writing batch files to perform various kinds of tasks. The people that frequented these groups were usually MS-DOS/Windows systems administrators. They were a target audience for the tools I had built so far.
I had noticed how complex some of the tasks some of them needed to write and maintain were. Sometimes the solutions were straightforward. Other times, the solutions worked with no external utilities, but the code to accomplish these tasks could be a little arcane.
ENVY
I had written a number of personal utilities that modified either a given process’ parent environment block or the master environment block using a number of schemes to locate this area of memory. The environment block was a section of memory that held the MS-DOS environment variables for a given process. I had pondered a utility that would provide some straightforward programming commands that would leave their results in the specified environment variable in the parent environment block. I quit pondering and I implemented ENVY, a 16-bit program for MS-DOS.
Syntax:
ENVY option
Where option can be one of the following:
-checkenv number
-checkmax number
-clearenv
-compare num op num
-copy var srcvar
-ctime var
-date var
-dec var
-deletevar var
-eko str1 .. strN
-expr var term operator term
-filename var [drive path basename ext ] filenameandpath
-findinpath filename
-getdir var
-getxy varx vary
-gotoxy numberX numberY
-inc var
-index var str srchstr
-key var
-lcase var str
-length var str
-loadenv filename
-match str srchstr
-random var max+1
-readln var
-replace var str chr1 chr2
-saveenv filename
-seterrorlevel number
-sleep seconds
-sprintf var str1 .. strN
-substr var str start length
-time var
-ucase var str
-word var num str
-wordcount var str
-write var filename
-writeln var filename
ENVY added 37 new utility functions for batch file developers. Many of those functions that returned one or more results, left the results in an environment variable. With ENVY, one could write a batch file that might look something like this:
@echo off
set x=1
:loop
echo x is %x%
envy -inc x
envy -compare %x% gt 10
: if x isn't greater than 10, goto loop.
if errorlevel 1 goto loop
The above script should print ten lines saying “x is” followed by the value of x.
I sold a few copies of ENVY. I made the choice to quit selling it after having to deal with a few support issues where people were trying to use it with the Windows NT cmd.exe interpreter.
BPL
While I gave up on ENVY, I hadn’t given up on the idea of a supplement for batch scripts. I wrote a simple interpreter for a one-operation-per-line language that I called BPL … “Batch Programming Language.” BPL was an interpreter whose scripts looked sort of like batch files. Here’s an example BPL script that demonstrates BPL’s math capabilities:
echo "Math demo"
echo
set a 2
set b 5
add c $a $b
echo $a " plus " $b " equals " $c
sub c $a $b
echo $a " minus " $b " equals " $c
mul c $a $b
echo $a " times " $b " equals " $c
div c $a $b
echo $a " divided by " $b " equals " $c
mod c $a $b
echo "The remainder of " $a " divided by " $b " is " $c
and c $a $b
echo $a " and " $b " is " $c
or c $a $b
echo $a " or " $b " is " $c
xor c $a $b
echo $a " exclusive-or " $b " is " $c
pause
…which yields the output
Math demo
2 plus 5 equals 7
2 minus 5 equals -3
2 times 5 equals 10
2 divided by 5 equals 0
The remainder of 2 divided by 5 is 2
2 and 5 is 0
2 or 5 is 7
2 exclusive-or 5 is 7
Press ENTER to continue...
A fellow named Tom registered some copies of BPL and then he emailed me. Tom used to write various kinds of business software using a PC-based COBOL compiler. He used BPL for all of the administrative tasks around that software … using it to choreograph scheduled executions and such. He loved it. In fact, I believe that he was the one who talked me into implementing a while-loop and another feature or two to help deter “spaghetti code” that can often plague languages that are dependent on a GOTO verb for flow-control.
Other than those few who registered the product, BPL did not really seem to resonate with most folks. I was competing with any number of automation languages. The niche that I tried to cover was syntactic simplicity when compared to the other offerings. I had mentioned writing a BPL compiler so that one could package up BPL scripts into a single distributable EXE, but I didn’t pursue that. I still wonder if I should have built the compiler.
I stopped selling BPL because the sales just weren’t there. It wasn’t really taking off.
Run & Hide
Run & Hide was a utility that would run a command in a hidden console window. I’d heard some folks mention that people were hitting CTRL-BREAK during some batch startup scripts, which caused a few problems. I thought that this might be a common problem that Windows sysadmins might’ve been facing.
I ended up selling around twenty copies before I pulled the plug on it. There were some Windows Scripting Hosts scripts making the rounds in the newsgroups that provided the same function.
Epilogue
I should note that all three of the above products were written in C. ENVY was written using a 16-bit C compiler.
Three more products that ended up not doing well. I had an idea for another product which fared better than all of these products combined. I’ll talk about that one soon.
CMD2EXE … Kind of Like a Batch File Compiler
For some personal needs, I built a C program that would act as kind of an installer tool. I embedded some files to the executable. When run, the executable would extract the files and it would invoke a specific one as a batch file. I formalized the code a bit yielding a new utility: CMD2EXE.
CMD2EXE was based on a simple C runtime stub. When executed, the stub would check for files that had been appended to it. It would write them to a temporary directory and it would invoke one that had been specified. All of this was managed by keeping a string literal in the stub that would hold the size of the executable stub. The internal code would call the atoi() function on the string literal to convert it to a size. The code would then open itself … the EXE … for reading beginning at the next address after the number specified by the string literal. Injecting the size into that field was just part of the build process.
This was an easy way to embed a batch file into an executable. It was pretty popular. It was under MailGrab in terms of sales. Despite the popularity, I ran into a few problems.
Anti-Virus Software
Someone must have use CMD2EXE to encode a nefarious payload for a virus. One of my customers contacted me saying that they could no longer use the tool to package executables. I tried it myself. They were correct. Apparently, some data strings in the CMD2EXE stub were catlogued as belonging to a virus. I worked with some AV companies to stop this, but it happened after that … more than once.
Security Constraints
Some AV / Anti-Malware software was starting to prevent programs from writing scripts to temporary file areas and executing them. There are perfectly normal reasons for doing this, but I was in no position to try to fight this.
A Couple of Last Features
I remember adding the ability to hide the console window on execution ( building in functions from Run & Hide ). I also added the ability to run a series of commands sequentially instead of writing them out to a file. This was a very inefficient way of executing commands in batch, but it was the only way that would not be scrutinized by AV and security software.
Eventually, I stopped selling CMD2EXE. It was quite handy and it was popular. I was going to expand it with instructions on running a variety of scripting languages from within a packaged EXE. There were a number of tools emerging to do this at the time, so I felt no urgency to throw my hat into the ring. I felt that this approach was just trying to leverage a technique that fell out of favor with modern security practices.
ScreenKap - Command-Line Screen Capture
The next product that I wrote was a simple command-line screen capture utility called ScreenKap. It was written in C. It used the same graphics library that I had purchased for WallShow and WallMake. ScreenKap existed in two forms; a console mode application and a Windows UI application. The UI application didn’t really have a user interface … it just didn’t bring up a dark console window while trying to capture the screen contents.
I experimented with some new forms of copy protection with this utility. I embedded a date into ScreenKap that would force it to stop working after that date. I had previously used dates that needed to be written to files based on the date of the first use and such. I thought this would be an easy way to ensure that no special “write” privileges were needed by the end user. I used to place an expire date of about thirty to forty-five days out or so. Remembering to update the software in a timely manner became kind of a chore. I wouldn’t recommend doing something like that unless you can automate the process.
I also experimented with encrypting all of the string literals in the code. I wrote string constants in kind of a meta language that was near the top of the C program in comments. It would have been something like this:
//def thanks "Thank you for using my software!"
//def email "You may contact me at jimbo@radiks.net"
#include "vars.c"
I used an AWK preprocessor to scan through the ScreenKap file, looking for lines that began with //def. The output was then an encoded string in a file called vars.c which I would immediately #include into the main C program. It might’ve looked something like this:
vars.c
char *thanks="---encrypted stuff here---";
char *email="--even more encrypted stuff here--";
Each time I needed to reference a literal, I would call a decode function that would decrypt the literal on the fly. I was just trying to make it difficult to alter the code’s literal strings. It worked well, but for some reason, this triggered false positives in a whole slew of Anti-Virus products. I don’t know if the encoded strings were standing out as unusual or if the AV software was attempting a heuristic approach to virus detection and couldn’t figure out why an honest software artisan would encrypt their string literals.
It wasn’t that important to me, so I changed the AWK script to generate lines of pure string literals:
new vars.c
char *thanks="Thank you for using my software!";
char *email="You may contact me at jimbo@radiks.net";
I changed the decrypt function call so that it was basically a benign C macro. I submitted the update to all of the AV vendors and got a clean bill of health within an evening. I have to hand it to the AV companies. I don’t like having my software flagged as being suspicious, but their ticketing systems and remediation processes are pretty smooth and while they do take a little while, they are pretty painless.
I sold ScreenKap via RegSoft for a number of years. When RegSoft closed up shop, I moved it to FastSpring. I’ll talk just a bit more about FastSpring in the next post.
ScreenKap was not a killer application. In fact, I read an Internet post from a guy who was thoroughly disgusted that he needed to pay for command-line screen capture software, so he wrote his own. His take was that desktop software should be free … web software … now, that’s worth paying for. This was becoming a pervasive way of thinking thanks to tablet and smartphone app pricing. After retiring the software in my next post, I also took ScreenKap off the market.
I struggled with whether I needed to provide an open source version of ScreenKap, but I didn’t for a couple of reasons. One was that the source was dependent on a third-party library that I had licensed. The other reason was that I thought that one could probably build a better command-line screen capture utility in C#. I might give that a whirl, some time.
MailWrench - MailSend’s Heir Apparent
I had been supporting MailSend for about fourteen years. I had regularly fixed bugs and added a feature here or there. It was showing its age regarding modern mail agents that could leverage secure SSL connections to SMTP servers. I had written up a document on using the open source program STunnel as an intermediary between MailSend and SMTP/SSL servers, but that just seemed to be very kludgy. It was kludgy and I was taking money for a program and telling people how to use a free program to get more out of it. That didn’t seem right.
I was looking into using SSL libraries with MailSend when I got an email from a frequent customer. The customer had explained that they used to purchase copies of MailSend for third parties who used their systems. I knew this to be true as I frequently saw them registering a few copies here and there throughout the year. They had asked if I could support Windows authentication with Microsoft Exchange servers. I said that I’d look into it.
I had toyed with the idea of rewriting MailSend in C#. It seemed to have all of the features that compiled AWK gave to me, as well as access to the .NET subsystem. After a bit of research, I found that the standard .NET SMTP interface supported both the Exchange authentication that my customer had requested and it supported the Secure Sockets Layer.
Instead of creating a new version of MailSend, I wanted to come up with a unique name. The new tool might later incorporate reading POP3 or IMAP email, so I didn’t want to limit the name with the word “Send.” I landed on the name MailWrench … an email tool. I was able to secure the domain name mailwrench.com immediately. I went to work first designing the feature set, then coding. Here is a help screen detailing MailWrench’s options:
MailWrench v 2.00
by Jim Lawless - jimbo@radiks.net
Syntax:
MailWrench [options] where options are:
-h Display this screen
-s subject Specify subject
-a filename Attach filename
-f filename Attach files in list
-smtp smtp_addr Specify SMTP server address
-port number Specify port ( default is 25 )
-to to_address Specify 'To:' e-mail address
-from from_address Specify 'From: address
-file text_file Name of text file to send
-msg string Specify immediate message to send via the command-line
-filter Take text file input from the console stdin device
-out Redirect output to specified filename
-suppress Suppress output ( except for error messages )
-cc to_address Carbon-copy one recipient; Can be specified multiple times
-ccf filename Carbon-copy all recipients listed in filename
-bcc cc_address Blind-cc one recipient; Can be specified multiple times.
-bccf filename Blind-carbon-copy to all recipients listed in filename
-receipt Request return-receipt
-disp Request disposition notification
-ch header value Add custom header(s)
-html Send file as HTML
-timeout Maximum timeout ( in seconds )
-img number filename Attach an image as an inline resource in HTML
-priority code Set priority. { low, normal, or high }
-ntlm Perform NTLM authentication with the mail server
Used for SMTP authentication.
-id loginID User ID
-password password User's password
-domain domainID Used if authenticating explicitly against a Windows domain
-ssl Use a Secure Sockets Layer connection (SMTPS)
Options can be combined in a text file to save command-line space.
See the documentation for detailed information.
MailWrench sold a few copies here and there right away, but it never reached the popularity of MailSend. The customer who had requested the NTLM features never did register a copy of MailWrench. They were quite diligent about paying for copies of MailSend, so I suspect that in the time it took me to write MailWrench, they had found another command-line emailer that met their needs.
With MailWrench, I wanted to try out a new registration processor, just for this product. I had been happy with RegSoft, but there were reasons that I thought it wise to investigate a different payment processor. I’m afraid I can’t remember what those reasons were except that it might’ve pertained to the selling of their company. I’d heard good things about a new payment processor, FastSpring, so I gave them a try. They were a bit different than RegSoft, but they were very professional from the get-go. I signed up with them and I saw regular sales of MailWrench.
The sales of the product were low enough that it didn’t seem to be wise to keep trying to sell it, so I pulled the plug in July of 2012. I placed the product’s source code on my Github page. I changed the compiled version so that it was free of charge. Even at free, not many were interested in it.
Because it was written in C# targeting .NET, I did experiment running MailWrench under what is now called MacOS using Mono and, after a bit of certificate setup, it ran perfectly. As a side note, I believe that the .NET SMTP libraries I used are now deprecated. There are new libraries that are in favor. If I needed to use MailWrench nowadays, I would likely have to give it a bit of a face-lift.
I am still not quite sure what to make of this experience. Certainly development tools were maturing. Email integration was becoming just a standard set of libraries in most programming language offerings. My market was likely no longer a niche.
It was worth my time as I thought that I had everything going for this product. I had some primary market research from one customer indicating that there was a need for Windows authentication. I’d had others ask for the SSL integration, so that was proof, too. In planning for the rollout of the product, I had taken the time to come up with a unique name … something that permitted me to secure my own unique “.com” domain name. That really didn’t do much for me. I set up shop with a new registrar who was really great to work with. The problem was that the sales were just too low.
Withdrawing MailWrench ( and ScreenKap ) from public sales meant that I was no longer an independent developer of desktop software. Oh, I’ve been writing more software. I just don’t charge for it, nor do I necessarily promote it.
What’s Next
I had a lot of fun selling my own software for a while. I encountered some interesting folks along the way.
People
A person from France registered MailSend by sending me a $10 bill in the mail … from France to the United States. It made it to me! He said that was the most convenient way for him to pay me in U.S. funds. For a while, I kept all of the envelopes from customers who sent registrations via postal mail. I had a number of them from various places around the globe.
A young woman approached me about removing the limitations of the trial version. She told me that she tried everything to avoid paying for it, but she finally spent the $10.
There was a guy who used social engineering to make me think that a co-worker of his had ordered a copy of MailSend and that they were in desperate need of it. So, I sent him a link to the fully-functional version. I never heard from him again.
I hadn’t realized that people would be unfamiliar with the term “Windows console mode application.” They would click MailSend.EXE after downloading. This caused the early versions to open a DOS-looking window which then immediately closed after the help text was displayed. One guy thought I had broken his OS because he had problems after double-clicking my software. He and I worked through whatever was happening on his system. I later changed MailSend so that there was a pause requiring the operator to hit ENTER after displaying a portion of the help text. This allowed people to examine the console screen without freaking out about the “weird DOS window that popped up.”
My software was once an attachment to this huge group email where everyone kept replying to all “take me off of this email list” … which kept sending emails … with my software link … to hundreds of folks who had already seen these emails.
I was surprised at how handy my command-line mail tools were for people using some older tech. A few people were using some older versions of Nantucket’s Clipper xBase language. They were able to use MailSend and MailGrab to automate email processing from their programs. One customer used QBASIC to drive MailSend and MailGrab for a mail automation system for his church.
The person who owns the hosting company for the original mailsend-online.com page, NetOne Communication https://netonecom.net , was one of my customers. He personally urged me to obtain my own domain and he guided me through hosting on his service. Originally, I had just used my personal web page at my ISP to host my downloads. Then, my ISP changed hands and my home page’s URL now had a tilde (~) in the URL where it hadn’t before, breaking all of the links I had placed throughout the Internet. I should’ve secured my own domain much earlier.
Later Stuff
Although I quit selling software, I didn’t quit publishing software. I think my most popular utility is my command-line MP3 player (cmdmp3) that I wrote just to exercise the Windows Multimedia API’s.
See: https://github.com/jimlawless/cmdmp3
At one time, I had a command-line Twitter client called Twimmando. Twitter changed their API’s quite a while ago, which broke the utility. I have also published various batch utilities and other programs over the years.
I also tested the mobile waters with a free Android app. I had been meaning to release some apps for both Android and iOS, but it can be really tough to do so. If you actually sell the apps, taxes seem to be something that can be kind of a pain.
Thank you all. The years that I’ve discussed in this series of posts were quite a fun ride!