Is there a faster way of moving data between databases than CTEs?
This doesn't have anything to do with using a CTE specifically, as your question title implies. It is probably a combination of at least one or more of the following: 


an expensive scan (or seek + a million lookups) to identify the rows to delete (I assume [Receive Date] is not the clustering key)
many underlying non-clustered indexes that also must be updated
blocking (both on the delete and on the target/archive table)
a batch size too large that causes too much transaction log activity (which can be especially bad if you have poor t-log configuration)


See this blog post but generally you may want to delete in smaller chunks and inject some artificial delays and/or checkpoints / log backups in between each individual delete.