Spam, Newsletters and RSS

Email newsletters have survived the web, but anti-spam initiatives will take them down. Blacklists, whitelists and challenge/response are the rage in the war against spam. But blacklists are broad and draconian, whitelists leak spam with forged addresses, and challenge/response systems cannot distinguish between opt-in and spam. The war on spam will inevitably force publishers to convert from email to RSS.

I imagine you could subscribe to a newsfeed of your interests and the headlines would be customized to you … publishers would establish a feed and people would add the feed

Unfortunately, not everyone has a RSS reader. Newsletter producers are in for a bumpy ride over the next few years.

Blacklists: people have been taught that unsubscribing to spam only serves to confirm your email address. So they often opt to brand a newsletter as spam rather than unsubscribe.

Whitelists: 100 × zero is still zero. Spam will be sent multiple times with forged from addresses. Whitelists will create a new market for “clean from addresses.” And newsletters will be prime candidates.

Challenge/Response: the fundamental problem is that sending spam is free. Challenge/response systems work by attaching a cost to each email. That will kill the free newsletter.

Sample Newsletters:

13 May: Confessions of a Former Spammer via Marketing Fix.

I'm LinkedIn

Ok, I’ve been complaining that my network didn’t survive my move from the West to the East Coast for a couple of years now. So how could I resist an opportunity to resuscitate it electronically. With an assist from Rogers Cadenhead, I’m taking LinkedIn out for a spin.

Singing His Favorite Tune

I hope that Eric’s not holding his breath on this one. Because I think that I’ve got a better chance of seeing a cross platform application server from Microsoft than he has of seeing a cross platform client.

I want a cross-platform story for managed code. Any story… Please make C# awesome. It is probably the last language I will ever use.

Microsoft will never own the server the way it owns the desktop. Corporations are already uneasy about the desktop monopoly, they’re not about to give Microsoft that same power on the server. And the existence of Linux acts as a soft cap on the cost of a Server OS. But there is money to be made with an application server. And a cross platform app server would build trust that the app server has a clean separation from the Windows OS.

While Linux has a solid foothold on the server, it has been a non-starter on the desktop. And the lack of software is a big part of what has been holding it back. Provide ISV’s with an easy path to migrate Windows applications to Linux and the desktop market would suddenly become much more interesting.

Go Ducks

I realize that some people cannot forgive The Mighty Ducks for their corporate owner or the owner’s movie of the same name, but the Ducks are the feel good story of the Stanley Cup Playoffs. I’m even ignoring the rule of rooting for the team that knocked out your team (which allows you to say that at least we got beat by the champions). There’s going to be a newcomer from the west in the finals with the big 3 knocked out (Colorado, Detroit and Dallas). I just hope that Ottawa can knock off NJ, because NJ has the kind of system that eats newcomers for lunch.

RSS Rocks

In case there was any doubt, I love RSS. It has changed the way that I interact with the internet. I didn’t understand RSS news aggregators until I actually started using one. And I only started using one because it was built into my weblog software Radio Userland. Now I don’t understand why everyone isn’t using one.

As the name implies, a news aggregator combines content from multiple sources and provides a consolidated view of what’s new. High volume sources typically distribute the headline with a short teaser hook, and a link back to the entire article. And low volume sites typically distribute the entire article. You browse high volume sites more efficiently because you only see the headlines with a teaser (and even those are loaded in the background). And you can follow more low volume sites because you aren’t constantly hitting them just to see if something is new.

Try one today.

[16 May] See Sharing Your Site with RSS.

Conditional Execution in Ant

In this Ant tutorial installment, we’ll take a look at the conditional execution of targets. Let’s start with the simple Hello World build file from before. Modify the hello and goodbye targets to include the if and unless attributes as shown in bold.

1
2
3
4
5
6
7
8
9
10
11
<project default="all">
<target name="hello" if="hello.set">
<echo message="Hello, World"/>
</target>

<target name="goodbye" unless="hello.set">
<echo message="Goodbye, Cruel World"/>
</target>

<target name="all" depends="hello,goodbye" />
</project>

The if=”named.property” attribute causes a target to be executed if the named property is set. And the unless=”named.property” attribute causes a target to be executed unless the named property is set. If we execute the build file without specifying a value for the property “hello.set”, then the hello target will be skipped and the goodbye target will be executed. And specifying a value for the property “hello.set” yields the opposite result.

1
$ ant
Buildfile: build.xml

hello:

goodbye:
     [echo] Goodbye, Cruel World

all:

BUILD SUCCESSFUL
Total time: 2 seconds
$ ant -Dhello.set=true
Buildfile: build.xml

hello:
     [echo] Hello, World

goodbye:

all:

BUILD SUCCESSFUL
Total time: 4 seconds

Of course, we could just specify the desired target on the command line and avoid all that. But let’s take a look at how we can use this to cleanup after a failed target. Start with the build file we used to run multiple JUnit test cases and split the original target “test” into three pieces: test-execute, test-failed, and test. Target “test-execute” will contain the JUnit task, target “test-failed” will contain the cleanup code and be conditional on if=”test.failure”, and target “test” will tie it all together. This will execute our clean up code if a test fails and skip the clean up code if all tests pass. Note that we could consolidate targets “test-failed” and “test” together at the cost of some clarity about the intent of each target.

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
<project default="all">
<property name="tst-dir" value="test" />
<property name="TALK" value="false" />

<path id="classpath.base">
</path>

<path id="classpath.test">
<pathelement location="/Projects/Java/Lib/junit.jar" />
<pathelement location="${tst-dir}" />
<path refid="classpath.base" />
</path>

<target name="compile-test">
<javac srcdir="${tst-dir}"
verbose="${TALK}"
debug="true"
>

<classpath refid="classpath.test"/>
</javac>
</target>
<target name="clean-compile-test">
<delete verbose="${TALK}">
<fileset dir="${tst-dir}" includes="**/*.class" />
</delete>
</target>

<target name="test-execute" depends="compile-test">
<junit failureProperty="test.failure">
<classpath refid="classpath.test" />
<formatter type="brief" usefile="false" />

<batchtest>
<fileset dir="${tst-dir}" includes="**/Test*.class" />
</batchtest>
</junit>
<fail message="test failed" if="test.failure" />
</target>

<target name="test-failed" depends="test-execute" if="test.failure">
<echo message="perform test cleanup" />
<fail message="test failed" />
</target>
<target name="test" depends="test-failed" />

<target name="all" depends="test" />

<target name="clean" depends="clean-compile-test" />
</project>

Execution with Test Failure

1
$ ant -f build.xml
Buildfile: build.xml

compile-test:

test-execute:
    [junit] Testsuite: Test
    [junit] Tests run: 1, Failures: 1, Errors: 0, Time elapsed: 0.035 sec

    [junit] Testcase: test(Test):	FAILED
    [junit] Equality Test expected:<0> but was:<1>
    [junit] junit.framework.AssertionFailedError: Equality Test expected:<0> but was:<1>
    [junit] 	at Test.test(Test.java:7)
    [junit] 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    [junit] 	at sun.reflect.NativeMethodAccessorImpl.invoke( ... .java:39)
    [junit] 	at sun.reflect.DelegatingMethodAccessorImpl.invoke( ... .java:25)


    [junit] TEST Test FAILED
    [junit] Testsuite: TestExample
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec


test-failed:
     [echo] perform test cleanup

BUILD FAILED
file:/Tutorial/Ant/Conditional/junit.xml:38: test failed

Total time: 3 seconds

Execution with Test Success

1
$ ant -f build.xml
Buildfile: build.xml

compile-test:

test-execute:
    [junit] Testsuite: Test
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.026 sec

    [junit] Testsuite: TestExample
    [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.001 sec


test-failed:

test:

all:

BUILD SUCCESSFUL
Total time: 4 seconds

Disclaimer: I don’t claim to be an expert on ant. Please send comments and corrections.

Is It The Shoes?

In one of the greatest ad campaigns of all time, Mars Blackmon asked Is it the Shoes? Of course, everyone knew that Michael Jordan playing in Chuck Taylors would still be great. So while it may have nothing to do with the tools, Scoble is being a little rough on management – it is not about control as much as it is about What’s in it for me?

So give management something that it wants. And lead with RSS – publish and subscribe sounds much less threatening than conversation.

  • Have a problem distributing information about application and server downtime and maintenance?
  • Is everyone asking about a problem at a critical customer site?
  • Does everyone want the latest on how the beta is coming along? These are tailormade for an RSS feed. Let it settle in for a while, then expand the scope from the internal to the trusted external, your partners and beta customers. And expand the internal scope from publish and subscribe to conversation, using weblogs in place of email for design discussions. Management will never know what hit them.

The Next Step in Trustworthy Computing

In the comments, Robert Scoble asks what could they build that +would+ convince you [that Windows is better than Linux for a server]? It won’t be easy, but Microsoft needs to take the next step in trustworthy computing: Trustworthy Design.

True or not, Windows is perceived to be a complex furball of code. Patches to fix problems in one area create surprising new behavior in other areas. Fixing a Buffer Overrun in Kernel Message Handling can slow your system to a crawl. As a consequence, Windows is perceived to be less stable that Linux – not because of the relative numbers of bugs, but because of the complexity and ramifications of the bugs.

Microsoft needs to build trust in the design of Windows: trust that complexity is managed by good design and trust that components are isolated from faults in other components. Actions speak louder than words. And acts like embedding IE tightly into the OS speak quite loudly.

Open Source and Innovation

According to Steve Ballmer, our customers have seen a lot more innovation from us than they have seen from that [Linux] community. That’s not completely correct, but then it’s not completely wrong either. Open source is capable of innovative features. And it lags in innovative products.

Innovative products go hand in hand with new markets. And new markets usually take time and money. Time to work with customers and to refine the product. Money for marketing to establish the new market. And both to redirect the product if it started with a dud. Open source products need to start with a near miss – otherwise they never achieve critical mass and become another SourceForge zombie.

But the server market is not innovation driven. IT wants stability, not innovation. And IT is perfectly happy with “a clone of a 20-year-old system” as long as it supports their application requirements (and received 20 years of continued refinement).

Money vs. Marketing

Some performers prefer that you buy from a major record store rather than their table at the show. It’s a question of money vs. marketing. The starving newcomer and the comfortable oldtimer will usually prefer the extra money from an immediate sale with no middle men. The up and comers often prefer sales at a major record store – because store sales are tracked and they need sales numbers to move up the list at both the store and the label.

Along those lines, Apple’s iTunes Music Store can be judged a success when the entertainment media reports download sales with the same alacrity they report CD sales and box office revenue.