What you want is to find the 2-edge-connected components of your graph.
When you have a simple graph, you can do that by finding all bridges in your graph in linear time, delete them and find the connected components in the resulting graph (every connected component corresponds to a vertex in the final graph).
Now to ensure that this works also in your case where you can have multiple edges between two vertices you can simply ignore when the above algorithm finds an incorrect bridge (u,v), where u and v are connected by multiple edges. Don't delete this edge from your graph when this happens. To detect when this happens you can first find all duplicate edges (either by sorting all edges first or using some hashing method), store those edges in a container where they can efficiently be searched (hashing or binary search) and then for every detected bridge, test if it is in that container.